JEE6 - #ApplicationException - #Inject and #PostConstruct not called - exception

I have a problem with #Inject and #PostConstruct method not called in a #ApplicationException annoted class. I'm using Glassfish 3.0.1 with JPA,CDI and EJBs in the service(=ejb)-layer and would like to throw an errorMessage that contains a text in the sessionlanguage.
I have an abstract ExceptionClass
public abstract class LocalizedException extends Exception {
private static final long serialVersionUID = 1L;
String localizedMessage;
//This method should be called as #PostConstruct from the concrete classe
protected void setLocalizedMessage(LocaleHandler localeHandler, String key){
this.setLocalizedMessage(localeHandler, key, new Object());
}
protected void setLocalizedMessage(LocaleHandler localeHandler, String key, Object... args){
localizedMessage = ErrorMessages.getErrorMessage(key,localeHandler.getAktuelleLokale(),args);
}
#Override
public String getMessage() {
return localizedMessage;
}
#Override
public String getLocalizedMessage() {
return localizedMessage;
}}
And a concrete class:
#ApplicationException
public class ConcreteException extends LocalizedException {
private static final long serialVersionUID = 2615388267911318734L;
private int userId;
public ConcreteException(int userId) {
this.userId=userId;
}
public int getUserId() {
return userId;
}
#PostConstruct
#Inject
public void initText(LocaleHandler localeHandler){
setLocalizedMessage(localeHandler, "msgKey");
}
}
The LocaleHandler (=Sessionscoped) should be injected to provide the currentLocale which is used to retrieve an errormessage from a bundle.
The problem is, that the #PostConstruct is never called no matter what I try. I even annoted the concrete class with #Named, used #Inject in the concrete class instead of the abstract, but nothing works. When I call initText() directly I can see (in the debugger), that the LocaleHandler is not injected.
Now I'm asking myself if there is a restriction regarding Exception classes and CDI or did I simply not find the source of the problem !
Do you know the answer ?
thanx in advance
Thomas

The problem is solved.
I simply used the Exception as throw new ConcreteException(), as I'm used to since ages. Excactly this was the problem. Now I inject the ConcreteException into my EJB and throw the containercreated field. This way #Inject and #Postconstruct are working !

Related

Unit Test class not running properly - Mocking Interfaces

I have a simple Controller class like below:-
#RestController
public class CrawlerAppController {
private static final Logger LOGGER = LoggerFactory.getLogger(CrawlerAppController.class);
#Autowired
private CrawlerServiceInterface crawlerService;
/* The response time of the crawling operation is directly proportional to the no of pages
* we want to crawl. Keeping a default value of 10 so we can view the results quicker.
* author: Arunava Paul
*/
#RequestMapping(value = "/crawl", method = { RequestMethod.GET })
public Object crawlUrl(#RequestParam(value = "URL") String URL,
#RequestParam(value = "max", defaultValue = "10") int maxPages) throws Exception {
if(!URL.startsWith("https://"))
URL="https://"+URL;
LOGGER.info("Request Received. Domain "+URL+" Pages to be Crawled "+maxPages);
return crawlerService.crawlService(URL, maxPages);
}
}
I have written a Junit class like below:-
#RunWith(PowerMockRunner.class)
public class CrawlerAppControllerTest {
Object obj=new Object();
#Spy
#InjectMocks
private CrawlerServiceInterface crawlerService = Mockito.any(CrawlerService.class);
#InjectMocks
CrawlerAppController appController = new CrawlerAppController();
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testController() throws Exception {
when(crawlerService.crawlService("https://vogella.com", 20)).thenReturn(obj);
assertEquals(appController.crawlUrl("vogella.com",20), obj);
}
}
It's always going into the Service class and the when statement is not running.
Can someone please advise what have I done wrong. Below error comes if I run Junit.
You should declare crawlerService like this:
#Mock
private CrawlerServiceInterface crawlerService;
The declaration of crawlerService in the test class should be:
#Mock
private CrawlerServiceInterface crawlerService;

Failed to instantiate com.fasterxml.jackson.databind.node.ObjectNode using constructor NO_CONSTRUCTOR with arguments In MongoDB

I'm using JsonNode for getting data from any kind of jason format and storing it to mongoDb
But while fetching data from mongoDB it is throwing error as below.
Failed to instantiate com.fasterxml.jackson.databind.node.ObjectNode using constructor NO_CONSTRUCTOR with arguments
Below is my domain class
public class Profiler {
#Id
private String id;
#Field("email")
private String email;
#Field("profiler")
private Map<String,JsonNode> profiler;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Map<String, JsonNode> getProfiler() {
return profiler;
}
public void setProfiler(Map<String, JsonNode> profiler) {
this.profiler = profiler;
}
public Profiler(String email,Map<String,JsonNode> profiler){
this.email=email;
this.profiler = profiler;
}
#JsonCreator
public Profiler(#JsonProperty("_id")String id,#JsonProperty("email")String email,#JsonProperty("profiler")Map<String,JsonNode> profiler){
this.id=id;
this.email=email;
this.profiler = profiler;
}
public Profiler(String id){
this.id=id;
}
public Profiler(Map<String,JsonNode> profiler){
this.profiler = profiler;
}
public Profiler(){
}
}
public interface ProfilerRepository extends MongoRepository<Profiler, String>{
public Profiler findOneByEmail(String email);
}
And my controller call is as below and I'm getting the error on this line.
Profiler profile=profileService.findOneByEmail(email);
I have made this changes and work as expected.
Map<String, Object> profile;
This problem occurs because com.fasterxml.jackson.databind.node.ObjectNode class doesn't have default constructor (no argument constructor) and Jackson expects the default constructor.
Related Post refer azerafati's answer
The problem can be resolved if you define the profiler field as static in domain class.
private static Map<String, JsonNode> profiler;
Please note that static fields have its own limitations and issues. I can assure that this would resolve the above exception. However, it may not be the most appropriate solution.
in my case problem solved . i had entity that i defined :
private JsonNode data;
i changed it to:
private Map<String,String> data;
or this also work :
private Map<Object,String> data;
please let me know if you had any question

NodeEntity wont persist

I have the following NodeEntity:
#NodeEntity(label = "Book")
public class Book{
private Long id;
private String content;
#Relationship(direction = Relationship.OUTGOING, type="WRITTEN_BY")
private User author;
}
where User is
#NodeEntity(label = "User)
public class User{
private Long id;
private String username;
}
and the BookRepository
#Repository
public interface BookRepository extends GraphRepository<Book> {
}
I've build a simple Rest-Controller to store a Book in the DB.
#Controller
#ResponseBody
#RequestMapping(path = "/books", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#Transactional
public class BookController {
#Autowired
private BookRepository bookRepo;
#RequestMapping(method = RequestMethod.POST)
public Book createBook(#RequestBody Book book) {
return bookRepo.save(book);
}
When I now POST a Book the JSON
{
"content":"Test content",
"author":{
"username":"Test-Username"
}
}
to the controller, two things happen that confuse me:
First, the author in the book-object is null, although both the Book and the User have their default constructor.
Secoundly: The Book doesn't get persisted. There is no error, I just get the same book-object returned (with the author still null) but still with a null id.
Querying MATCH n RETURN n on the neo4j client also yields nothing.
I tried removing the User object from the `Book, thinking the fault was there, but I still get the same behavior.
What am I doing wrong?
Sometimes talking about a problem alone solves it... I've forgotten to put the package that contained the Book into the
#Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(/*Package of Book should have been here*/);
}
in the Application

Parsing map of object to a json

I've read countless articles about parsing Java objects to JSONs and still have issues...
I know that there are a bunch of frameworks out there and this is where things messed up I guess.
I'm trying to parse a map into a json:
Map<CategoryBean, Double> questionsPercentagePerCategory;
here's how CategoryBean looks like:
#XmlRootElement
public class CategoryBean implements Serializable{
private static final long serialVersionUID = -7306680546426636719L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
questionsPercentagePerCategory is a variable inside a wrapper json called: PrePracticeBean
and this is how it looks:
#XmlRootElement
public class PrePracticeBean implements Serializable {
private int maxQuestionsAllowedForUser;
private int maxQuestionsAllowedForUserAfterCreditOver;
private int questionsInExam;
#XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
private Map<CategoryBean, Double> questionsPercentagePerCategory;
private static final long serialVersionUID = -655358519739911024L;
public int getMaxQuestionsAllowedForUser() {
return maxQuestionsAllowedForUser;
}
public void setMaxQuestionsAllowedForUser(int maxQuestionsAllowedForUser) {
this.maxQuestionsAllowedForUser = maxQuestionsAllowedForUser;
}
public int getMaxQuestionsAllowedForUserAfterCreditOver() {
return maxQuestionsAllowedForUserAfterCreditOver;
}
public void setMaxQuestionsAllowedForUserAfterCreditOver(int maxQuestionsAllowedForUserAfterCreditOver) {
this.maxQuestionsAllowedForUserAfterCreditOver = maxQuestionsAllowedForUserAfterCreditOver;
}
public int getQuestionsInExam() {
return questionsInExam;
}
public void setQuestionsInExam(int questionsInExam) {
this.questionsInExam = questionsInExam;
}
public Map<CategoryBean, Double> getQuestionsPercentagePerCategory() {
return questionsPercentagePerCategory;
}
public void setQuestionsPercentagePerCategory(Map<CategoryBean, Double> questionsPercentagePerCategory) {
this.questionsPercentagePerCategory = questionsPercentagePerCategory;
}
}
as you can see I've marked both beans with #XmlRootElement annotation to get Jeresey's OOB bean to JSON parsing functionality as specified here
Furthermore, here's how the XMLGenericMapAdapter looks like:
public class XmlGenericMapAdapter<K, V> extends XmlAdapter<MapType<K, V>, Map<K, V>> {
#Override
public Map<K, V> unmarshal(MapType<K, V> orgMap) throws Exception {
HashMap<K, V> map = new HashMap<K, V>();
for (MapEntryType<K, V> mapEntryType : orgMap.getEntries()) {
map.put(mapEntryType.getKey(), mapEntryType.getValue());
}
return map;
}
#Override
public MapType<K, V> marshal(Map<K, V> v) throws Exception {
MapType<K, V> mapType = new MapType<K, V>();
for (Map.Entry<K, V> entry : v.entrySet()) {
MapEntryType<K, V> mapEntryType = new MapEntryType<K, V>();
mapEntryType.setKey(entry.getKey());
mapEntryType.setValue(entry.getValue());
mapType.getEntries().add(mapEntryType);
}
return mapType;
}
}
Well, the end result is what makes me crazy... it's intermittent... when running the code in debug mode, this works flawlessly showing a nested json for the map and each key:value pair is another nested json. However, when invoked in run mode, I get an ugly "memory address" instead of the CategoryBean key...
My only guess is that this is related to class loading matters and that I might be having some other JAR that's having a class which is loaded first in debug mode but not in run mode...
anyways, any suggestions as to how this should be done, would be appreciated.
thanks,
GBa.
Well, solved...
some JAXB/Jersey stuff which I'm not into understanding up to the last bit... but I bet that there's some JAXB guru out there who could give the right explanation why this is the case...
Anyways, bottom line is that the CategoryBean class should not have the annotation #XmlRootElement but instead should have #XmlAccessorType(XmlAccessType.FIELD)
I got the inspiration for that from Serializer for (Hash)Maps for Jersey use?
thanks,
GBa.

GWT Autobean without setter method

I am using Autobean framework to encode/decode JSON in my GWT application. It works in cases with the interfaces having getters and setters. But is there any way to do it some other way to do this without specifying a setThisCollectionProperty instead using an addToThisCollectionProperty method?
For example, I have an interface IPerson like this:
public interface IPerson {
public String getName();
public void setName(String name);
public int getAge();
public void setAge(int age);
public List<String> getIds();
public void addId(String id);
}
BeanFactory is like this:
public interface BeanFactory extends AutoBeanFactory {
public AutoBean<IPerson> person();
public AutoBean<IPerson> person(IPerson person);
}
and in Person class which implements IPerson,
public class Person implements IPerson {
private String name;
private List<String> ids;
...
public List<String> getIds() {
return ids;
}
public void addId(String id) {
...
ids.add(id);
}
}
It works if the addId(String id) is replaced with setIds(List<String> ids).
Otherwise the following error is shown:
The com.mycompany.jsonsample.beans.IPerson parameterization is not simple, but the person method does not provide a delegate
Is it possible to encode/decode without a set method?
AutoBean manages all getters and setters, and only getters and setters. For any other method, you have to use a category.
Using a category, you could thus implement addId(…) as getIds().add(…), or possibly directly call addIds on the underlying object if the AutoBean is a wrapper.