i'm using lastest version of zoom-sdk, and i'm getting the following error:
Duplicate class com.google.android.exoplayer2.video.spherical.package-info found in modules exoplayer-core-2.16.1-runtime (com.google.android.exoplayer:exoplayer-core:2.16.1) and library-core-release-runtime (library-core-release.aar)
Duplicate class com.google.android.exoplayer2.video.spherical.TouchTracker$Listener found in modules exoplayer-core-2.16.1-runtime (com.google.android.exoplayer:exoplayer-core:2.16.1) and library-core-release-runtime (library-core-release.aar)
Duplicate class com.google.android.exoplayer2.video.spherical.TouchTracker found in modules exoplayer-core-2.16.1-runtime (com.google.android.exoplayer:exoplayer-core:2.16.1) and library-core-release-runtime (library-core-release.aar)
......
And
implementation("com.google.android.exoplayer:exoplayer-datasource:2.17.0") { exclude group: "com.google.android.exoplayer", module: "exoplayer-common" }
implementation("com.google.android.exoplayer:exoplayer-decoder:2.17.0") { exclude group: "com.google.android.exoplayer", module: "exoplayer-common" }
in my build.gradle(:app) for video player, when i remove implementations app works fine with zoom-sdk but video player no longer work.
Looks like your project uses two versions of exoplayer, "2.17.0" and "2.16.1".
Replace your implementation of Exoplayer with this:
implementation("com.google.android.exoplayer:exoplayer-core") {
version {
strictly("2.17.1")
}
}
implementation("com.google.android.exoplayer:exoplayer-ui") {
version {
strictly("2.17.1")
}
}
This will force your project to use one version of Exoplayer as "2.17.1"
Related
Just starting a new Gradle project.
This test passes:
def 'Launcher.main should call App.launch'(){
given:
GroovyMock(Application, global: true)
when:
Launcher.main()
then:
1 * Application.launch( App, null ) >> null
}
... until, to get another test using a (Java) Mock to work, I have to add these dependencies:
testImplementation 'net.bytebuddy:byte-buddy:1.10.8'
testImplementation 'org.objenesis:objenesis:3.1'
(NB I assume these versions are OK for Groovy 3.+, which I'm now using ... both are the most up-to-date available at Maven Repo).
With these dependencies the above test fails:
java.lang.InstantiationError: javafx.application.Application
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
at org.objenesis.ObjenesisHelper.newInstance(ObjenesisHelper.java:44)
at org.spockframework.mock.runtime.MockInstantiator$ObjenesisInstantiator.instantiate(MockInstantiator.java:45)
at org.spockframework.mock.runtime.MockInstantiator.instantiate(MockInstantiator.java:31)
at org.spockframework.mock.runtime.GroovyMockFactory.create(GroovyMockFactory.java:57)
at org.spockframework.mock.runtime.CompositeMockFactory.create(CompositeMockFactory.java:42)
at org.spockframework.lang.SpecInternals.createMock(SpecInternals.java:47)
at org.spockframework.lang.SpecInternals.createMockImpl(SpecInternals.java:298)
at org.spockframework.lang.SpecInternals.createMockImpl(SpecInternals.java:288)
at org.spockframework.lang.SpecInternals.GroovyMockImpl(SpecInternals.java:215)
at core.AppSpec.Launcher.main should call App.launch(first_tests.groovy:30)
I confess that I have only the sketchiest notion of what "bytebuddy" and "objenesis" actually do, although I assume it is fiendishly clever. Edit: having just visited their respective home pages my notion is now slightly less sketchy, and yes, it is fiendishly clever.
If an orthodox solution to this is not available, is it by any chance possible to turn off the use of these dependencies for an individual feature (i.e. test)? Possibly using some annotation maybe?
Edit
This is an MCVE:
Specs: Java 11.0.5, OS Linux Mint 18.3.
build.gradle:
plugins {
id 'groovy'
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
repositories { mavenCentral() }
javafx {
version = "11.0.2"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
dependencies {
implementation 'org.codehaus.groovy:groovy:3.+'
testImplementation 'junit:junit:4.12'
testImplementation 'org.spockframework:spock-core:2.0-M2-groovy-3.0'
testImplementation 'net.bytebuddy:byte-buddy:1.10.8'
testImplementation 'org.objenesis:objenesis:3.1'
// in light of kriegaex's comments:
implementation group: 'cglib', name: 'cglib', version: '3.3.0'
}
test { useJUnitPlatform() }
application {
mainClassName = 'core.Launcher'
}
installDist{}
main.groovy:
class Launcher {
static void main(String[] args) {
Application.launch(App, null )
}
}
class App extends Application {
void start(Stage primaryStage) {
}
}
first_tests.groovy:
class AppSpec extends Specification {
def 'Launcher.main should call App.launch'(){
given:
GroovyMock(Application, global: true)
when:
Launcher.main()
then:
1 * Application.launch( App, null ) >> null
}
}
The reason why this project needs something to call the Application subclass is explained here: it's so that it is possible to do an installDist which bundles in JavaFX.
Don't we have to use a global GroovyMock?
If you want to check the interaction, yes. But actually you are testing the JavaFX launcher rather than your application. So I doubt that there is any benefit. I would focus on testing the App class instead. Also imagine for a moment that you would write the classes with main methods in Java instead of Groovy. Groovy mocks would not work when called from Java code, especially not global ones. Then you would end up testing via Powermockito from Spock, which would also work but still you would test the JavaFX launcher rather than your application.
Also isn't it slightly extreme to say any use of Groovy mocks is wrong?
I did not say that. I said: "probably something is wrong with your application design". The reason I said that is because the use of Groovy mocks and things like mocking static methods are test code smells. You can check the smell and then decide it is okay, which IMO in most cases it is not. Besides, instead of application design the problem can also be in the test itself, which in this case I would say it is. But that is arguable, so I am going to present a solution to you further below.
In this case technically the global Application mock is your only way if you do insist to test the JavaFX launcher because even a global mock on App would not work as the launcher uses reflection in order to call the App constructor and that is not intercepted by the mock framework.
you say that Spock spock-core:2.0-M2-groovy-3.0 is a "pre-release". I can't see anything on this page (...) which says that. How do you know?
You found out already by checking out the GitHub repository, but I was just seeing it in the unusual version number containing "M2" like "milestone 2" which is similar to "RC" (or "CR") for release candidates (or candidate releases).
As for the technical problem, you can either not declare Objenesis in your Gradle script because it is an optional dependency, then the test compiles and runs fine, as you already noticed yourself. But assuming you need optional dependencies like Objenesis, CGLIB (actually cglib-nodep), Bytebuddy and ASM for other tests in your suite, you can just tell Spock not to use Objenesis in this case. So assuming you have a Gradle build file like this:
plugins {
id 'groovy'
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
repositories { mavenCentral() }
javafx {
version = "11.0.2"
modules = ['javafx.controls', 'javafx.fxml']
}
dependencies {
implementation 'org.codehaus.groovy:groovy:3.+'
testImplementation 'org.spockframework:spock-core:2.0-M2-groovy-3.0'
// Optional Spock dependencies, versions matching the ones listed at
// https://mvnrepository.com/artifact/org.spockframework/spock-core/2.0-M2-groovy-3.0
testImplementation 'net.bytebuddy:byte-buddy:1.9.11'
testImplementation 'org.objenesis:objenesis:3.0.1'
testImplementation 'cglib:cglib-nodep:3.2.10'
testImplementation 'org.ow2.asm:asm:7.1'
}
test { useJUnitPlatform() }
application {
mainClassName = 'de.scrum_master.app.Launcher'
}
installDist {}
My version of your MCVE would looks like this (sorry, I added my own package names and also imports because otherwise it is not really an MCVE):
package de.scrum_master.app
import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.control.Label
import javafx.scene.layout.StackPane
import javafx.stage.Stage
class App extends Application {
#Override
void start(Stage stage) {
def javaVersion = System.getProperty("java.version")
def javafxVersion = System.getProperty("javafx.version")
Label l = new Label("Hello, JavaFX $javafxVersion, running on Java $javaVersion.")
Scene scene = new Scene(new StackPane(l), 640, 480)
stage.setScene(scene)
stage.show()
}
}
package de.scrum_master.app
import javafx.application.Application
class Launcher {
static void main(String[] args) {
Application.launch(App, null)
}
}
package de.scrum_master.app
import javafx.application.Application
import spock.lang.Specification
class AppSpec extends Specification {
def 'Launcher.main should call App.launch'() {
given:
GroovyMock(Application, global: true, useObjenesis: false)
when:
Launcher.main()
then:
1 * Application.launch(App, null)
}
}
The decisive detail here is the useObjenesis: false parameter.
Update: Just for reference, this is how you would do it with a launcher class implemented in Java using PowerMockito.
Attention, this solution needs the Sputnik runner from Spock 1.x which was removed in 2.x. So in Spock 2 this currently does not work because it is based on JUnit 5 and can no longer use #RunWith(PowerMockRunner) and #PowerMockRunnerDelegate(Sputnik) because PowerMock currently does not support JUnit 5. But I tested it with Spock 1.3-groovy-2.5 and Groovy 2.5.8.
package de.scrum_master.app
import javafx.application.Application
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.spockframework.runtime.Sputnik
import spock.lang.Specification
import static org.mockito.Mockito.*
import static org.powermock.api.mockito.PowerMockito.*
#RunWith(PowerMockRunner)
#PowerMockRunnerDelegate(Sputnik)
#PrepareForTest(Application)
class JavaAppSpec extends Specification {
def 'JavaLauncher.main should launch JavaApp'() {
given:
mockStatic(Application)
when:
JavaLauncher.main()
then:
verifyStatic(Application, times(1))
Application.launch(JavaApp)
}
}
I am experimenting with Gradle to build a few jars, rather than maintain a list of classes that hold EJBs so that I can deploy them separately I thought it might be neat to scan the classes when making the jar.
Rather than load the classes and use reflection to get the annotations I thought it may be simpler to scan the classes with asm, hence the chuncky ClassReader in one of the tasks.
I don't think this is the issue so can be ignored, basically I have 2 tasks that I use to define the contents of the jars, both report that different content is going into them via the eachFile print out, however when I look in the publish repository location both files and associated sha1 are identical.
Either Gradle is broken or, more likely, I've done something crazy but can't see what it is, can anyone help?
By the way if I disable the publish of either of the jar files the one that does get created is correct so I think it's something wrong with the publish rather than the jarring up, but could be wrong.
// ASM is used to interpret the class files, this avoids having to load all classes in the vm and use reflection
import org.objectweb.asm.*
task ejbJar(type: Jar) {
//outputs.upToDateWhen { false }
from "${project.buildDir}/classes/main"
eachFile { println "EJB server: ${name}" }
include getEjbClassFiles(project.buildDir)
}
task clientEjbJar(type: Jar) {
//outputs.upToDateWhen { false }
from "${project.buildDir}/classes/main/com/company/core/versioner"
eachFile { println "Client EJB ${name}" }
include '**/*'
}
artifacts {
archives clientEjbJar
archives ejbJar
}
String[] getEjbClassFiles(base) {
def includedFiles = []
def baseDir = project.file("${base}/classes/main")
def parentPath = baseDir.toPath()
if (baseDir.isDirectory()) {
baseDir.eachFileRecurse(groovy.io.FileType.FILES) { file ->
if(file.name.endsWith('.class')) {
//get hold of annotations in there --- org.objectweb.asm.Opcodes.ASM4
def reader = new ClassReader(file.bytes).accept(
new ClassVisitor(Opcodes.ASM4) {
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if(desc.equals("Ljavax/ejb/Stateless;") ||
desc.equals("Ljavax/ejb/Stateful;")) {
includedFiles += parentPath.relativize(file.toPath())
}
return null //no interest in actually visiting the annotation values
}
},
ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES | ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE
)
}
}
}
return includedFiles
}
publishing {
publications {
mypub(IvyPublication) {
artifact(ejbJar) {
name 'ejb'
}
artifact(clientEjbJar) {
name 'client-ejb'
}
}
}
repositories {
ivy {
name 'personal'
url "${ant['developer.repository']}/"
layout 'pattern', {
artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]"
ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]"
}
}
}
}
I did break the thing down into a simpler form as I thought it may be a Gradle bug.
The simplified form was:
apply plugin: 'java'
apply plugin: 'ivy-publish'
task bigJar(type: Jar) {
from "${rootDir}/src/main/resources"
include '**/*'
}
task smallJar(type: Jar) {
from "${rootDir}/src/main/resources/A/B"
include '**/*'
}
group 'ICantBeEmpty'
artifacts {
archives bigJar
archives smallJar
}
publishing {
publications {
mypub(IvyPublication) {
artifact(bigJar) { name 'biggie' }
artifact(smallJar) { name 'smallie' }
}
repositories {
ivy {
name 'personal'
url "c:/temp/gradletest"
layout 'pattern', {
artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]"
ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]"
}
}
}
}
}
This results in 2 files in c:/temp/gradletest/ICantBeEmpty/report-bug/biggie/unspecified/biggie-unspecified.jar and c:/temp/gradletest/ICantBeEmpty/report-bug/smallie/unspecified/smallie-unspecified.jar
Both of these files are identical, however I think I know why see my later answer.
Whilst looking at some configurations I noticed some odd behaviour that led me to a resolution of this issue, and it is a Gradle bug.
In my build I had a scratch task doing
configurations.archives.artifacts.each { println it }
This gave me 5 different lines output, however changing it to this
configurations.archives.artifacts.each { println it.file }
produced the same filename 5 times.
It turns out this is related to my issue, although the artifacts are there as separate entities the name used to uniquely identify them was the same so the same file was always chosen during a publish. The name of the artifacts is given by ${baseName}-${appendix}-${version}-${classifier}.${extension} by default in the java plugin. This means that if neither appendix or classifier is specified then the artifact will have the same name.
I tested this using the above sample code by adding an appendix name
task bigJar(type: Jar) {
appendix = 'big'
from "${rootDir}/src/main/resources"
include '**/*'
}
task smallJar(type: Jar) {
appendix = 'small'
from "${rootDir}/src/main/resources/A/B"
include '**/*'
}
Using this rather than the code from the question produces 2 different jars.
It's not a complete answer but is a good enough work around, if I add a new publication definition I can publish the artifacts that I want to to the location that I want, the only downside is that it will create another gradle task which isn't ideal.
publications {
mypub(IvyPublication) {
artifact(ejbJar) {
name 'ejb'
}
}
newpub(IvyPublication) {
artifact(clientEjbJar) {
name 'client-ejb'
}
}
}
The above answer works in the short term, however does reveal yet another short coming in the Gradle world enter link description here
Not sure Gradle is all it could be at the moment, and so far no one has answered my questions so maybe it's not that actively developed!!
I'm no expert in this part of Gradle, but the functionality you are using is marked as "incubating"; you are using the new publishing feature which might or might not be complete. Perhaps you should use the old way of doing things. You also seem to be mixing both ways by using the artifacts closure.
Is there a way to check in manifest files if a given class exists?
I want to do something like this:
class foo {
if exists( Class["foo::${lsbdistcodename}"] ) {
include foo::${lsbdistcodename}
}
}
So I can easily add distrubution / version specific classes which are then automatically included.
You should use defined instead of exists statement.
The following snippet works for me:
class foo {
if defined( "foo::${lsbdistcodename}") {
notify {'defined':}
include "foo::${lsbdistcodename}"
}
}
class foo::precise {
notify{'precise':}
}
[assuming you're running puppet version > 2.6.0]
I have a gradle project that has java applications as well as android applications.
root/
build.gradle
settings.gradle
java1/
java2/
android1/
android2/
java3/
etc.
What is the best practice for structuring my build script? I am a total gradle novice and am migrating the project from maven to gradle.
I wanted to do something instead of
configure(subprojects) {}
to apply plugins and other specific things.
such as
configure(java1, java2, java3) { // java specifics }
configure(android1, android2) { // android specifics }
I am probably approaching this from the wrong way.
More explicitly I need to apply the plugin java only for the java projects and the android plugin for the android projects.
configure(subprojects.findAll {it.name == "java1" || it.name == "java2"}) {
Under the filtering section in the guide
Hope this helps someone else out.
There are multiple ways, depending on what you want... Some examples:
// Configures just project java1
project(":java1") { ... }
// Configures projects java1 and java2
["java1","java2"].each { name ->
project(":$name") { ... }
}
You can use normal groovy to find/iterate over all the projects.
Another option:
configure([ project(':sub1'), project(':sub2'), ... ]) {
...
}
The shortest and easiest option:
configure(subprojects.findAll()) {
if (it.name.equals('MY_PROJECT')) {
...
} else {
...
}
}
Another approach...
In the settings.gradle you do define your projects like this:
gradle.ext.javaProjects=[]
gradle.ext.androidProjects=[]
javaProject('java1')
javaProject('java2')
javaProject('java3')
androidProject('android1')
androidProject('android2')
def javaProject(String name) {
gradle.ext.javaProjects.add(name)
include ":$name"
}
def androidProject(String name) {
gradle.ext.androidProjects.add(name)
include ":$name"
}
Now you can reference those in your root build.gradle:
def javaProjects = subprojects.findAll {gradle.ext.javaProjects.contains(it.name)};
def androidProjects = subprojects.findAll {gradle.ext.javaProjects.contains(it.name)};
configure(javaProjects) {
...
}
configure(androidProjects) {
...
}
Maybe thats overkill... but i usually have the project definition method in my settings.gradle anyway. E.g. if you want to put all java projects under a java folder you could define things like this:
def javaProject(String name) {
gradle.ext.javaProjects.add(name)
include ":$name"
project(":$name").projectDir = file('java/'+ name)
}
I'm trying to create module for magento. It use my own class
class Myfirm_Extname_Model_Mysql4_Product_Option extends Mage_Catalog_Model_Resource_Product_Option
In magento 1.7 all works fine, in 1.5 - error: Error class Mage_Catalog_Model_Resource_Product_Option not found.
How can I make class that will be inherited from Mage_Catalog_Model_Resource_Product_Option or Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Option depending on the version of magento?
I solved this prodblem.
protected function _getResource() {
if (version_compare(Mage::getVersion(), '1.6.0', '<')) {
$this->_resourceName = $this->_resourceName.'_oldversion';
}
if (empty($this->_resourceName)) {
Mage::throwException(Mage::helper('core')->__('Resource is not set.'));
}
return Mage::getResourceSingleton($this->_resourceName);
}
And then create 2 resource model class for old version of magento and new