How to: SLF4J with multiple bindings in a GWT Maven multi-module project? - gwt

I have a GWT multi-module Maven project.
Layout:
pom.xml
client-module //client side: contains some base classes. I use JDK's java.util.log so that it logs on Firebug's console
server-module //server side: extends some code from client-module (so it uses JUL) for common behaviour. I use log4j
client-module is shared code.
I want to use SLF4J globally but it seems that I cannot use multiple bindings (multiple bindings per project, single binding per maven module).
I would agree, but I want to use a specific SLF4J binding per maven module.
So in my case would be SLF4J-JDK for client-module and SLF4J-log4j for server-module.
Pieces of relevant code:
pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.3</version>
</dependency>
client-module/BaseFoo.java
public abstract class BaseFoo {
private static final Logger logger = LoggerFactory.getLogger(BaseFoo.class.getName());
// ... interesting stuff
}
server-module/Foo.java
public class Foo extends BaseFoo {
private static final Logger logger = LoggerFactory.getLogger(BaseFoo.class.getName());
// ...more interesting stuff
}
I have already tried to configure according to documentation, but it doesn't work.
The problem is that SLF4J needs to be GWT ready.
The error I get:
[ERROR] Line 23: No source code is available for type org.slf4j.Logger; did you forget to inherit a required module?
What it means that GWT compiles the BaseFoo class to Javascript (that's why is it in client-module to run on client side) but fails because the classes/source code in SLF4j are not emulated.
Do you have any workarounds?
Thanks!

Related

Error while creating building a hibernate app without Maven

I am learning to hibernate so I made a small app for crud operation using mySQL as database. However, I am getting some errors and I cannot find the solution anywhere. SDK 17.0.2, I am not using maven , Also all hibernate final jar files have been added
my class:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.luv2code.hibernate.demo.entity.Student;
public class CreateStudentDemo {
public static void main(String[] args) {
// Create session factory
SessionFactory factory= new Configuration()
.configure("hibernate.cfg.xml")
.addAnnotatedClass(Student.class)
.buildSessionFactory();
//Create session
Session session = factory.getCurrentSession();
try {
//Create a Student object
System.out.println("Creating new student");
Student tempStudent = new Student("Pau;", "Wall", "paul#luv2code.com");
//Start a transaction
session.beginTransaction();
//save the student object
session.save(tempStudent);
//commit transaction
session.getTransaction().commit();
}
finally {
factory.close();
}
}
}
runtime error :
java.security.PrivilegedActionException: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String,[B,int,int,java.lang.ClassLoader,java.security.ProtectionDomain)
Caused by: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String,[B,int,int,java.lang.ClassLoader,java.security.ProtectionDomain)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "com.sun.xml.bind.v2.runtime.reflect.opt.Injector.defineClass" is null
java removed java.xml.bind from JAVA 9 and higher editions.
You need to add these jar files manually to your library
basically you can to that in this way.
If you use Intellij this is the easyest way:
jaxb-impl-2.3.0.jar
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
jaxb-core-2.3.0.jar
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
jaxb-api-2.3.1.jar
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
javax.activation-api-1.2.0.jar
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
If you use intellij here is a step my step to get these files through IDE
go to project structure:
Libraries, and click + sign
Chick to from Maven:
Paste these dependencies to the search.
It will automatically find exact jar files to download, Kist Paste it and click to the enter that is it.
Also later you can just add these files to the classpath just in case:
java removed java.xml.bind from JAVA 9 and higher editions.
Here is the eclipse solution:
In Eclipse IDE:
Download these jar files and paste them inside lib folder:
Go the project properties: The last line
Done these steps:
Happy Coding! :)

open api swagger-ui giving white label error page (404) after moving the project as a module in a project

I have the working project in Spring boot which was a standalone app. Now, to modularize, I have split the app and put the api in a module. Earlier the swagger-ui.html page was working, but after this, it is not working.
my pom.xml has these 2 dependencies
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.5.1</version>
</dependency>
My Application.java has the following code
#Bean
#Profile("!prod")
public OpenAPI caffeAPIRegistry() {
return new OpenAPI()
.info(new Info().title("My Awesome API")
.description("Powering UI")
.version("v3.0.0")
.license(new License().name("google Inc.,").url("https://google.com")));
}
The pom.xml fragment for the parent project mapping
<parent>
<artifactId>API_Project</artifactId>
<groupId>com.abc</groupId>
<version>2.0.0.RELEASE</version>
</parent>
I have been searching for a long time in internet if moving api as a module might require any other change, but could not find any help.
Are the interfaces with the REST annotations in a different package? if yes then that is the issue.

Kafka - spring cloud stream

I am trying to use spring-cloud-stream with kafka. Below is the sample code. But it does not seem to do anything. It always creates a topic called 'output'. But the values are not published.
application.yaml
spring.cloud.stream:
function:
definition: streamSupplier
bindings:
streamSupplier-out-0:
destination: numbers
My aim is to just produce values.
#SpringBootApplication
#EnableBinding(Source.class)
public class CloudStreamDemoApplication {
private AtomicInteger atomicInteger = new AtomicInteger();
public static void main(String[] args) {
SpringApplication.run(CloudStreamDemoApplication.class, args);
}
#Bean
public Supplier<Integer> streamSupplier(){
return () -> {
System.out.println("Publishing : " + atomicInteger.incrementAndGet());
return atomicInteger.get();
};
}
}
dependency - 2.2.6.RELEASE
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
You need to remove #EnableBinding(Source.class) from the class. If that is present, the functional bindings will not take place.
Annotation #EnableBinding has caused the issue as explained above.
Read the below excerpts from spring Docs:
Unlike previous versions of spring-cloud-stream which relied on #EnableBinding and #StreamListener annotations, the above example looks no different then any vanilla spring-boot application. It defines a single bean of type Function and that it is. So, how does it became spring-cloud-stream application? It becomes spring-cloud-stream application simply based on the presence of spring-cloud-stream and binder dependencies and auto-configuration classes on the classpath effectively setting the context for your boot application as spring-cloud-stream application. And in this context beans of type Supplier, Function or Consumer are treated as defacto message handlers triggering binding of to destinations exposed by the provided binder following certain naming conventions and rules to avoid extra configuration.

How to enable Eclipse auto-completion in application.yml for custom properties declared by #ConfigurationProperties?

I made a simple class with configuration properties for my spring-boot project. Everything work as a charm (spring-boot catches options) except the fact that Eclipse doesn't recognize new properties as valid options in application.yml and highlights them as unknown.
Here is the class:
#Component
#ConfigurationProperties(prefix="server")
public class ServerProperties {
private Integer delay;
private DataAdapter dataAdapter = new DataAdapter();
// setters and getters were cut out for the sake of readability
public static class DataAdapter {
private String baseUrl;
private String targetCode;
// setters and getters
}
}
Autocompletion does not work for those properties:
I added the dependency for Spring Boot Configuration Processor to pom.xml as recommended in Spring.io reference, but it does not work as supposed.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Tried to switch to application.properties but autocompletion still doesn't work.
Spring boot configuration processor works as an annotation processor during compilation time.
It's necessary to enable annotation processing for the Eclipse project and register the processor:
Go to Project / Properties menu
Open Java Compiler / Annotation Processing. Enable project specific settings and check "Enable annotation processing"
Open Java Compiler / Annotation Processing / Factory Path. Check "Enable project specific settings"
Click "Add variable" button, select "M2_REPO", click "Extend" and find org/springframework/boot/spring-boot-configuration-processor/x.x.x.RELEASE/spring-boot-configuration-processor-x.x.x.RELEASE.jar in the Maven repository, where x.x.x is version of your Spring Boot.
Apply changes
Recompile the project, or just touch and save the class with configuration properties to trigger partial recompilation.
I had the same problem and fixed it by adding this to my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

CQ5 QueryBuilder Reference in Sling Servlet

I am declaring a sling servlet like so
#Component(metatype = false)
#Service(Servlet.class)
#Properties({
#Property(name = "sling.servlet.paths", value = "/bin/foo/bar"),
#Property(name = "sling.servlet.methods", value = "POST") })
public class FooBarServlet extends SlingAllMethodsServlet {
...
}
I override doPost like so
#Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
...
}
And I am able to post from a client. Great!
I throw in the following
#Reference
private QueryBuilder queryBuilder;
as per the documentation, a reference to query builder should be injected. But it does not seem to. In the log I see this error
bindQueryBuilder cannot be found (java.lang.VerifyError: ...
And when I try to post to the servlet I get this
javax.jcr.RepositoryException: org.apache.sling.api.resource.PersistenceException: Resource at '/bin/foo/bar' is not modifiable.
And in the OSGi console I see my bundle is installed, and this is what it has to say about my servlet
Service ID 3075 Types: javax.servlet.Servlet
Service PID: com.myproject.FooBarServlet
Component Name: com.myproject.FooBarServlet
Component ID: 5526
Vendor: Adobe
Any suggestions as to what I am doing wrong?
I had been using this tutorial as a reference.
I came across this about the Felix Service Component Runtime (SCR)
and so I implemented the following
protected void activate(ComponentContext context) {
LOGGER.info("activating {}", this.getClass().getName());
}
protected void unbindQueryBuilder(QueryBuilder queryBuilder) {
this.queryBuilder = null;
}
protected void bindQueryBuilder(QueryBuilder queryBuilder) {
this.queryBuilder = queryBuilder;
}
and it worked! So upon closer investigation I learned that these bind/unbind methods are actually supposed to be generated by the maven-scr-plugin, of which I have version 1.6.0
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
<configuration>
<!-- Private service properties for all services. -->
<properties>
<service.vendor>Adobe</service.vendor>
</properties>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.5.2</version>
</dependency>
</dependencies>
</plugin>
and for the annotations I have 1.4.0
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.4.0</version>
<scope>provided</scope>
</dependency>
so although I am not sure why the bind/unbind methods are not getting generated, I know that they should be, so I generate them manually.
Update
I tried to update the maven-scr-plugin to version 1.20.0, which yielded the following error during mvn build
[ERROR] Project depends on org.apache.felix:org.apache.felix.scr.annotations:jar:1.4.0:provided
[ERROR] Minimum required version is 1.9.0
so... I updated the org.apache.felix.scr.annotations to 1.9.0. And it works! My bind/unbind accessors are generated and all is great. However, I am concerned and do not know if I should use version 1.9.0 of org.apache.felix.scr.annotations because I am marking it as provided in the maven dependency and when I look at the OSGi bundles installed on the cq instance I see the following
Apache Felix Declarative Services (org.apache.felix.scr) : Version 1.6.3.R1409029
For the dependency injection to work, you should declare the member variable as public.
Try changing it to
#Reference
public QueryBuilder queryBuilder;