CQ5 QueryBuilder Reference in Sling Servlet - aem

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;

Related

Mapstruct is not generating implementation for one of my mapper interfaces. Is there a way to know the reason?

I am using mapstruct to map from/to domain objects to DTO
I have more than 20 mappers that are properly being generated.
One of my mappers is no longer being generated, but compilation is successful.
I use maven and i turned on showWarnings flag in the maven-compiler-plugin configuration, however i see no warnings regarding that specific mapper (I do see warnings for other mappers).
Is there a way to get some information from the annotation processor regarding mappers that are not being generated?
My mapper interface (with name changes):
#Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
PersonDTO map(Person entity);
Person map(PersonDTO dto);
}
My Maven configuration:
...
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.3.0.Final</version>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
...
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.3.0.Final</version>
</path>
</annotationProcessorPaths>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
You can do basic tracing (verbose mode) in the upcoming version of MapStruct. Checkout the documentation. You can try to use the latest MapStruct master in your project and see if it gives info on why this is not working.
For me it was a dependency issue.
My Projet A, had a dependency to another jar B, which contained the object from my mapper method.
That dependency B had a dependency C offering mapstruct mapper for many of the attribut of the object.
Somehow in my project A i was overriding explicitly the version of dependency C to an older version.
So it means that some of the Obj attribute from current B version where not matching with the older C mapper.
Mapstruct said nothing, just stopped generating the impl.
Not sure if this is very clear ... But check your dependencies.

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>

RestEasy Jax-RS in Jboss 7.1 doesn't work

I'm trying to deploy a simple web application under JBoss AS 7.1 which comes bundled with resteasy. According to the documentation all that is needed is (at bare minimum) is an empty web.xml, a class with annotated #ApplicationPath("/mypath") and #Path("/other_stuff") for your other classes
The documentation I'm following is here:
https://docs.jboss.org/author/display/AS7/JAX-RS+Reference+Guide
https://docs.jboss.org/author/display/AS7/Java+API+for+RESTful+Web+Services+(JAX-RS)
Still, when I hit:
host:8080/warname/applicationpath/path
I receive a 404 error on the webpage but nothing in the logs.
Is there a configuration file I need to change in order for JAX-RS to work?
Thank you in advance for any help!
Empty web.xml will do.
Just add some resteasy dependency to your classpath. For instance, if you use maven you can add this to your pom.xml:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.1.GA</version>
<scope>provided</scope> <!-- provided if youre deploying to jboss as 7.1 -->
</dependency>
Then set up the application using only this class:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
}
Just to make sure, add a resource like this:
#Path("/hello")
public class HelloResource {
#GET
#Produces("text/plain")
public String helloResource() {
return "Hello! It's "+new Date();
}
}
And that's all you need. Deploy it at a JBoss AS 7.1 and get to it, say:
http://127.0.0.1:8080/mywarname/rest/hello
Edit:
I have created a java war maven project with the bare minimum strucutre:
-pom.xml
-src
|
--main
|
--java
|
--rest
|
--HelloResource.java
--JaxRsActivator.java
I called it simpleRest as seen below. All the archives are exactly as shown:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>simpleRest</groupId>
<artifactId>simpleRest</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.1.GA</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!-- So maven doesn't require web.xml -->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
HelloResource.java
package rest;
import java.util.Date;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/hello")
public class HelloResource {
#GET
#Produces("text/plain")
public String helloResource() {
return "Hello! It's "+new Date();
}
}
JaxRsActivator.java:
package rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
}
This generates a simpleRest.war (through mvn clean package). I then deploy it to a freshly installed JBoss AS 7.1.1.Final. As you can see, no reference is made to JAX-RS in the log during the deploy:
22:48:08,677 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "simpleRest.war"
22:48:09,318 INFO [org.jboss.web] (MSC service thread 1-4) JBAS018210: Registering web context: /simpleRest
22:48:09,492 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "simpleRest.war"
After that, the URL is available as expected:
http://127.0.0.1:8080/simpleRest/rest/hello
Notice that everything else gives a 404 error. But it is a different kind of 404.
http://127.0.0.1:8080/simpleRest/ gives:
HTTP Status 404 - /simpleRest/
That is a page not found error. On the other hand, http://127.0.0.1:8080/simpleRest/rest gives:
HTTP Status 404 - Could not find resource for relative : / of full path: http://127.0.0.1:8080/simpleRest/rest
That is a resource (REST service) not found error. This way you know JAX-RS is acting, though it did not have a handler for that path.
Take a look at jboss quickstarts: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/
You can get them from http://www.jboss.org/jbossas/downloads
These are working out of box. For helloword-rs quickstart I can see web.xml with content:
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
and also comment:
One of the way of activating REST Servises is adding these lines, the server is responsible for adding the corresponding servlet automatically. If the src folder, org.jboss.as.quickstarts.rshelloworld.HelloWorld class has the Annotations to receive REST invocation.
If you are using JBoss AS 7.1, you also need to add the "resteasy.resources" context parameter. You also need to send the init-param to the HttpServletDispatcher servlet.
I found the solution at the following link : http://www.javaroots.com/2013/05/creating-rest-services-with-rest-easy.html
Just one typo error(maybe!!) in the above link. In the "RootRestService" change the method signature of the getClasses() method to public Set<Class<?>> getClasses().
Thats it! It solved my 3 day headache. Hope it helps you too!! :)
Even though acdcjunior's answer is great and very thorough, i'd like to reinfoce Andrzej's answer.
It works as a charm and it is by far the more straightforward one. The JBoss quickstart samples (also available on GitHub) are always a great resource to answer questions like this one.

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

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!

JUnit + Maven + Eclipse: Why #BeforeClass does not work?

I am using JUnit 4, Maven 2 and latest Eclipse. Problem is simple: I would like to perform some setup (connecting to a database) before my tests are executed.
I tried #BeforeClass in many different locations but Eclipse and Maven are ignoring this. Any help on accomplishing this initial setup?
Thanks!
public abstract class BaseTestCase extends TestCase {
#BeforeClass
public static void doBeforeClass() throws Exception {
System.out.println("No good #BeforeClass");
// DO THE DATABASE SETUP
}
}
Now the tests extending BaseTestCase:
public class LoginActionTest extends BaseTestCase {
#Test
public void testNothing() {
System.out.println("TEST HERE");
assertEquals(true, true);
}
}
Maven and Eclipse just ignore my #BeforeClass ??? Any other way to perform setup before tests?
Sergio, you were right about extending TestCase causing the problem. If you extend TestCase, JUnit treats your test class as an old (pre JUnit 4 class) and picks org.junit.internal.runners.JUnit38ClassRunner to run it. JUnit38ClassRunner does not know about #BeforeClass annotation. Check out source code of runnerForClass method of AllDefaultPossibilitiesBuilder and runnerForClass method of JUnit3Builder for more details.
Note: This problem is not related to Eclipse or Maven.
I suspect that you are running with JUnit 3. Try renaming your test to something which does not start with "test". If the test is no longer executing, you are using JUnit 3 (which assumes that test methods are methods which starts with "test").
Please post your Eclipse launch config.
I have similar problem and I fixed it by specifying surefile and junit versions explisitly:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
<configuration>
<parallel>methods</parallel>
<threadCount>10</threadCount>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
More info is here: http://maven.apache.org/plugins/maven-surefire-plugin/examples/junit.html
It seems junit 3.8.1 version is used transiently through maven-resources-plugin and plexus-container-default. You can print dependency tree by calling mvn dependency:tree. I think there's no other way to make surefire use junit 4.