Is there a way, in Scala and SBT, to automatically generate META-INF/services/* resource files for later use by java.util.ServiceLoader by annotating classes, like Google Auto Service does for Java projects?
i.e.
package foo.bar
import my.exported.ServiceInterface
#AutoService[ServiceInterface]
class MyService extends ServiceInterface{
// …
}
to automatically generate the file META-INF/services/my.exported.ServiceInterface in the resources folder. The file will contain:
foo.bar.MyService
(I don't think I can use Google Auto Service directly, as it doesn't work with Scala classes -- see this comment on a realm-java github issue.)
Please consider using https://github.com/nyavro/spi-plugin.
The approach used in this plugin differs from using annotations - it uses whole packages as a source of interfaces and applies to packages of interface implementations.
Related
I'm trying to build a Vert.X app using Scala, and generating the routes using an OpenAPI 3 spec through the OpenAPI3RouterFactory.
I need to generate the models described in my spec as Scala classes.
Is there any simple and straightforward way to accomplish this?
I'm using SBT to build my app, and I've already tried some sbt codegen plugins for Swagger, but none of them seem to work.
With vertx-web-api-contract, Router and validation handlers are generated at runtime, so you don't need to generate the routes. You can just start using the Router factory and mount the handlers you want as if it would be a Vert.x Web Router. If you want to bootstrap a new project there is a community tool called vertx-starter, but there is no Scala support now
Talking about the models, what you can do is organize your OpenAPI specification in different files, putting all data model definitions under a specific directory like spec/models (You can find a good guide here). Then you can configure jsonschema2pojo (sbt plugin) to generate a Scala case class for each schema inside that directory. Then, if you want to repack the spec in a single file, you can configure tools like swagger-cli to run during the compilation and pack the spec back in a single file
In Dependencies tab, I have a choice between plug-ins and packages.
What's the difference between them? For org.eclipse.compare, I have it in imported package and also in plug-ins.
I find the jar file in plugins directory, but I don't know where the package file of org.eclipse.compare is located.
In the export menu, it seems like that there seems to be only exporting to jar, not exporting a plugin or packages. How can I export packages?
ADDED
Based on this post - How to import a package from Eclipse? and shiplu's answer. This is what I came to understand. Please correct me if I'm wrong.
In eclipse, when I use come external class, I can use Quick-Assistant or Organize imports (Ctrl-Shift-O) to resolve the reference. Eclipse adds the package that contains the class in Imported Packages for the project that I'm working on. A package can contain multiple classes (types). Eclipse understands what plugin contains the package, and resolve the reference issues.
A plug-in (jar file) can contain multiple packages. By specifying a required plug-ins in the dependencies tab, we can reference all the packages (and classes in the packages) for all the java projects in the eclipse IDE.
And from my experience, I had to add all the dependencies in order to make headless RCP standalone (http://prosseek.blogspot.com/2012/12/headless-rcp-standalone.html).
An Eclipse plug-in is basically an OSGi bundle with additional plugin.xml file which Eclipse IDE understands and interprets.
So the answer to your question lies in the OSGi specification and the OSGi programming model, since, very simply put, Eclipse is an Application running on implementation of OSGi called Equinox.
OSGi is all about having modular applications and so it defines several levels of modularity.
One such level is a bundle-level (module-level) modularity and more fine grained level is the package level modularity.
So you can have your OSGi application (a set of bundles; eclipse is just that) which consists of db-bundle (which provides data store services), app-domain-bundle (which provides your application domain services) and remote-bundle (which exposes to the web your application via REST for example).
And then you say remote-bundle depends on domain-bundle which depends on db-bundle.
Which is all good, but cripples the inherent modularity OSGi provides, because you are basically restricting your application to specific implementations of db-bundle and remote-bundle i.e. to specific implementations of the services they provide.
Instead, you can establish the above dependencies not between bundles but between packages i.e. establish a service-level dependencies.
Then you say domain-bundle requires dbstore.service package to run, it doesn't care which bundle provides it it just needs an instance of this service to be able to work. So you can have multiple bundles providing implementations of the dbstore.service, and the domain-bundle can pick and choose at runtime what service to use.
It is really hard to explain OSGi concepts in just a several sentences, I'd really suggest you dig around the web on this and maybe even have a look at the OSGi specification.
Another way to explain it is to say that bundle/plug-in is a jar file with specific structure and metadata descriptors (MANIFEST.MF and plugin.xml), which describe its contents in Java language concepts - which java packages and services this specific jar contains and will expose to the OSGi runtime so that they can be consumed by other bundles. I.e. the bundle is the physical deployable entity while the descriptors are metadata about what actually is being deployed.
EDIT:
Package or Service-level dependencies also have some drawbacks, as Lii points out in the comments below, the main one being that it adds complexity and dynamics to the dependency model. Have a look at her or his comment below - it is worth reading!
You use Imported Packages when you want to use a specific package but do not care which plugin provides it. OSGI will choose one for you.
Eclipse plugins is something like extension to the IDE itself. But imported packages are actually packages that you'll use in your current project.
One is for development IDE another is for the project you are coding.
I am trying to extend a third-party Eclipse plug-in by using a fragment project. The major reason is that the third party plug-in contains classes having the default (package) modifier and I need to extend them.
Thus, my extensions class must be located in exactly the same package. I create a fragment project containing the same package and put my class into it. Everything works fine when I am using a runtime workspace.
However, if I try to deploy my fragment (e.g., deploying it into the dropins folder of my Eclipse distribution), I am not able to execute the code. Extensions and stuff like that work fine (e.g., I use extensions for a new Run Configuration. However, if I try to instantiate this run configuration I get an error message that the third-party root plug-in was unable to load the class to display my configuration tab group.
Any experience with this kind of problems?
Sorry, but that does not work. Unless the host bundle has been crafted specially for it, you cannot override a class in the host from a fragment. The reason is that resources - including classes - are retrieved from the host before any fragment.
See org.eclipse.osgi.baseadaptor.loader.ClasspathManager for the implementation..
Actually, this is the extension code I am using:
<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
class="com.android.ide.eclipse.adt.internal.launch.jouleunit.AndroidJouleUnitTabGroup"
id="com.android.ide.eclipse.adt.jouleunit.AndroidJouleUnitLaunchConfigTabGroup"
type="com.android.ide.eclipse.adt.jouleunit.launchConfigurationType">
</launchConfigurationTabGroup>
Of course, there are further extensions definig the launch configuration type etc. but this is the one leading to the class which Eclipse can not find.
Actually I found the problem now for myself. The problem was a wrong configured build properties file which excluded the Java byte code from my fragment JAR. Very itchy, as the classes were in the JAR but in a wrong subdirectory.
We are using a 3rd-party jar that contains a dependency to the log4j.varia.NullAppender class. We are transitioning to logback, but unable to change the 3rd-party jar, so we plan to use the log4j-over-sl4j bridge for now with the rest of our code still using the existing log4j calls.
Since the log4j-over-slf4j jar does not contain the NullAppender class, what is the best way to spoof it? Should we write our own and put it on the class path? Should we augment the log4j-over-slf4j bridge jar with this class?
What have others done who have run into this and does the logback project plan to support backwards compatibility? This is a real hassle for those of us who want to migrate when existing jar files use log4j classes that are not in the bridge.
Any suggestions or best practices?
Bottomline,
I'm using Grails 1.3.7 and using JPA annotated classes from a JAR file,
But the constraints are not working, meaning they are ignored even if I explicitly code them, like usual in the domain classes,
Is there a way I can get the constraints working?
#Don
1.- JPA classes are .java inside a jar file, I've created Grails Domain classes using this .java classes by just using the grails create-domain-class and using the corresponding package to the .java, so the outcome result in the grail project is
Domain
\
com.myapp.Clazz.groovy
\
package com.myapp.Clazz
class Clazz {
}
Later, I tried to add a Constraint.groovy file to the src/java folder with my constraints, as specified in the following article: Reuse your hibernate/jpa
But when I tried to run the app the compiler gets into an infinte cycle and never finish to compile the project..
Grails documentation here says, that if you annotate your class with #Validateable and provide a static constraints block inside class and register its package in Config.groovy, you will be able to validate this class as usual.