Pages

Monday, 24 March 2014

Including a Custom Tag within a Custom Tag File (tagx) using xml notation

Decided to write this up for reference as I had to go through the oracle java documents to finally find a solution. While there were solutions available, most of it concentrated on the tag file in a JSP document/xml notation. This blog can for a basis/example for writing a custom tag file (using the xml notation) rather than the java notation.

It all started with writing a tag file for creating a dropdown using an enum, which then I had to include in another custom tag for creating a table.

The first part was simple enough (though found few samples, could be due to the simplicity associated with creating a tag file), nevertheless I had to really struggle to get the things in order.

Step 1:
Decide the tag Library Name, in this case lets name it formtags.
Create a folder tags under the WEB-INF folder, this step is mandatory. Once can create any number of subfolders under this with the name of their choosing and then decide to include the same. This will help them better organize their tags.

Step 2:
Create a file with extension "tagx". Using the tagx instead of tag will ensure that your tag follows a well formed xml notation thus ensuring a better readability, hence decided to use this even though if you do a search for tag files there will be lots of examples for using the .tag but bery few for the document form of custom tags.
Add the jsp root element to the file thus ensuring that most the jsp and jstl core libraries are available.

<jsp:root xmlns:c="http://java.sun.com/jsp/jstl/core"
 xmlns:spring="http://www.springframework.org/tags"
 xmlns:jsp="http://java.sun.com/JSP/Page"
 xmlns:form="http://www.springframework.org/tags/form" version="2.0">
</jsp:root>

Now as you can see I have included the spring tags too, as I am using this with a spring application and this gives me the all powerful option to manipulate the java using el.
You can see the use of the spring el in the example below, where we would be touching the tip of the uses where this can be put into.

Step 3:
Define the attributes required by the custom tag.


<jsp:directive.attribute name="listEnumName" type="java.lang.String"
 required="true" description="Fully qualified Name of the Enum" />
<jsp:directive.attribute name="path" type="java.lang.String"
 required="true" description="Select Model Field Name" />

As you can see I have defined the two attributes namely
1) listEnumName -- This will be used to pass the name of the enum which would be used to form the options for the drop down to be created dynamically.
2) path -- Used the attribute Name path as it would be used to pass on the path variable into the form tag.

Step 4:
Get the list of values available in the Enum.

<spring:eval var="enumValList"
 expression="T(${ listEnumName }).values() " />

Note the use of T which indicates to the Spring el that the listEnumName has to be cast to a type and then execute the values method on the type. The list is then assigned to enumValList.

The Enum that I have used for reference (In the example below the enum implements EntityEnum which has been added by me just to ensure that i implement a few methods, the el should work even without it.


public enum SortTypeEnum implements EntityEnum<SortTypeEnum>{
 ASC("ASC"), DESC("DESC");

 private String value;
 
 private SortTypeEnum(String value) {
  this.value = value;
 }
 
 @Override
 public String getValue() {
  
  return this.value;
 }

 @Override
 public SortTypeEnum getEnumByValue(String enumValue) {
  for (SortTypeEnum fieldNameVal : SortTypeEnum.values()) {
   if (enumValue.equals(fieldNameVal.getValue())) {
    return fieldNameVal;
   }
  }
  return null;
 }
 
 
}



public interface EntityEnum<T extends Enum<T>> {

 public String getValue();
 
 public T getEnumByValue(String enumValue);
}

Step 5:Calling the Custom tag from within another tag. This is where, I had to struggle to include the tag directory and finally was able to find the solution after reading through this "Declaring Tag Libraries" .
Once known it was a simple affair to call the custom tag from within another custom tag.
 Providing below a sample for reference, the trick here is to include the namespace as a urn.
urn:jsptagdir:&lt;tag directory path&gt;


<jsp:root xmlns:c="http://java.sun.com/jsp/jstl/core"
 xmlns:spring="http://www.springframework.org/tags"
 xmlns:jsp="http://java.sun.com/JSP/Page"
 xmlns:form="http://www.springframework.org/tags/form" 
 xmlns:formtags="urn:jsptagdir:/WEB-INF/tags/formtags"
 version="2.0">
 
 <formtags:EnumSelect listEnumName="com.july11.framework.common.commonenum.SortTypeEnum" path="defaultSort"/>
</jsp:root>

One can use the normal taglibs also by using "urn:jsptld:&lt;Tld Path" instead of the jsptagdir.


Wednesday, 19 March 2014

SOLVED: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

I have a controller which is used for a simple String list response using JSON for a jquery autocomplete scenario. On invoking the url got the warning mentioned below and no response was received on the ajax call.

The details of the configuration is as mentioned below:

Note : The request url ending with ".html" which turned out to be the cause of the issue

Jquery for Ajax invocation:

var classList = "<c:url value='/common/classlist.html' />";
$(function() {
    var cache = {};
    $( "#modelClass" ).autocomplete({
      minLength: 2,
      source: function( request, response ) {
        var term = request.term;
        if ( term in cache ) {
          response( cache[ term ] );
          return;
        }
 
        $.getJSON( classList, request, function( data, status, xhr ) {
          cache[ term ] = data;
          response( data );
        });
      }
    });
  });

Controller:

@RequestMapping(value="/common/classlist", method=RequestMethod.GET)
public @ResponseBody List listValidClass(@RequestParam("term") String className){
  .. Return List
}

Maven Dependency:

 
   <jackson.version>2.3.2<jackson.version>

    <dependency>
        <groupid>com.fasterxml.jackson.core</groupid>
        <artifactid>jackson-databind</artifactid>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupid>com.fasterxml.jackson.core</groupid>
        <artifactid>jackson-annotations</artifactid>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupid>com.fasterxml.jackson.core</groupid>
        <artifactid>jackson-core</artifactid>
        <version>${jackson.version}</version>
    </dependency>


Web.xml:


 <servlet-mapping>
  <servlet-name>simple-form</servlet-name>
  <url-pattern>*.html</url-pattern>
 </servlet-mapping>



Error:

java.util.List com.july11.web.mvc.admin.controller.ValidClassController.listValidClass(java.lang.String)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation 
Resolution:
The possible solutions mentioned were:
1) Ensure that jackson classes are present in the class path -- This was already present as the maven dependency was included.
2) Most of the solutions concentrated on jackson 1.x -- Tried including the 1.9.10 version and removing the fasterxml (2.x) from the maven dependency, but still the problem persisted.
3) A few of the suggestions cited that a List cannot be returned as a JSON -- Tried wrapping the response in an object with getters and setters for retrieving the list.
4) Include the jacksonMessageConverter in the xpring context -- This was slightly tricky as there were equal number saying that the <mvc:annotation-driven /> should take care of registering the appropriate convertor.
5) Modify the mvc:annotation driven configuration to register MappingJackson2HttpMessageConverter

After spending a lot of time finally decided to debug the request and for this started out with a breakpoint HttpMediaTypeNotAcceptableException for all exceptions which lead me to AbstractMessageConverterMethodProcessor from where the exception was being thrown. A bit of additional debug let me know that the response header content type was being mapped to "text/html" whereas spring was expecting the response content type recevied in request to match a json.



I double checked my request traffic on the browser where it was expecting a json response. Further debugs on ContentNegotiationManager and PathExtensionContentNegotiationStrategy.getMediaTypeKey finally gave me actual issue.

Issue And Final Resolution:
The request url had the extension as html which is mapped to content type of text/html by the DispatcherServlet. At this point all i had to do was either accept a request (without any extension) or be a bit more explicit and change my request url to "/common/classlist.json" from "/common/classlist.html".

Added the additional mapping in webx.xml to handle the url mapping and everything started working as expected.

 <servlet-mapping>
  <servlet-name>simple-form</servlet-name>
  <url-pattern>*.json</url-pattern>
 </servlet-mapping>


Tuesday, 18 March 2014

SOLVED: NullPointerException thrown by Java Annotation Processing

The workspace i was using suddenly had errors related to the static meta model that are generated using the maven plugins during compile time. On checking further noticed that few of the meta model files were missing from the generated path. This looked strange as the same was working the previous day.
Tried the following without any luck:
1) Close my workspace and start it again.
2) Modify the File annotated with Entity so that the metamodel generates (This gave an error FileNotFound) in the .log file generated under the .metadata folder of the workspace.
3) A maven clean (which actaully removed all the generated srcs and new ones did not get generated).

Finally found a solution here. Just followed the steps to manually clean and build the project and voila everything went back to normal.

Error:

!ENTRY org.eclipse.jdt.apt.pluggable.core 1 1 2014-03-19 07:15:12.450
!MESSAGE Hibernate JPA 2 Static-Metamodel Generator 1.2.0.Final

!ENTRY org.eclipse.jdt.apt.pluggable.core 4 1 2014-03-19 07:15:12.490
!MESSAGE Exception thrown by Java annotation processor org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor@6d2418
!STACK 0
java.lang.NullPointerException
 at org.eclipse.jdt.apt.core.internal.AptCompilationParticipant.addJava6GeneratedFile(AptCompilationParticipant.java:272)
 at org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeProcessingEnvImpl.addNewUnit(IdeProcessingEnvImpl.java:132)
 at org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeJavaSourceOutputStream.close(IdeJavaSourceOutputStream.java:72)
 at sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:320)
 at sun.nio.cs.StreamEncoder.close(StreamEncoder.java:149)
 at java.io.OutputStreamWriter.close(OutputStreamWriter.java:233)
 at java.io.BufferedWriter.close(BufferedWriter.java:266)
 at java.io.PrintWriter.close(PrintWriter.java:339)
 at org.hibernate.jpamodelgen.ClassWriter.writeFile(ClassWriter.java:80)
 at org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.createMetaModelClasses(JPAMetaModelEntityProcessor.java:155)
 at org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.process(JPAMetaModelEntityProcessor.java:145)
 at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:139)
 at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.round(RoundDispatcher.java:121)
 at org.eclipse.jdt.internal.compiler.apt.dispatch.BaseAnnotationProcessorManager.processAnnotations(BaseAnnotationProcessorManager.java:159)
 at org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeAnnotationProcessorManager.processAnnotations(IdeAnnotationProcessorManager.java:134)
 at org.eclipse.jdt.internal.compiler.Compiler.processAnnotations(Compiler.java:820)
 at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:434)
 at org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:366)
 at org.eclipse.jdt.internal.core.builder.BatchImageBuilder.compile(BatchImageBuilder.java:178)
 at org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:303)
 at org.eclipse.jdt.internal.core.builder.BatchImageBuilder.build(BatchImageBuilder.java:60)
 at org.eclipse.jdt.internal.core.builder.JavaBuilder.buildAll(JavaBuilder.java:254)
 at org.eclipse.jdt.internal.core.builder.JavaBuilder.buildDeltas(JavaBuilder.java:270)
 at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:193)
 at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:733)
 at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
 at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:206)
 at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:246)
 at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:299)
 at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
 at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:302)
 at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:358)
 at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:381)
 at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:143)
 at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:241)
 at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)

Solution Steps:
1) Uncheck Build Automatically.
2) Clean all Projects
3) Refresh the Project
4) Check the Build Automatically setting Back.



Saturday, 15 March 2014

Steps to Create a Readonly User in Oracle with Select grant on all tables

I have explained the steps to be followed to create readonly user.

Step 1:
Create a Role with basic permission which can be used as a template for additional users if needed. The permissions granted to a role can be granted to a user directly in case a role based access is not required.


create role read;
grant create session to read;
--Optional
grant connect to read;
Grant create synonym to read;

Grant the create session permission so that the user with this profile is able to login into the database, once a user is granted this role the create session need not be explicitly added as it is carried over from the role.
The grant to create synonym has been added so that one can create synonyms for the tables from other schema instead of accessing the tables with scheme identifier.

Step 2:
Grant Select on all the tables in a Schema to a the read role. This can be done using a PL/SQL block mentioned below. Lets assume that we have to grant select on all tables belonging to the schema/user GTUSER, the below mentioned query can be executed.


BEGIN
 FOR x IN (SELECT * FROM dba_tables WHERE owner='GTUSER')
 LOOP
  EXECUTE IMMEDIATE 'GRANT SELECT ON GTUSER.' || x.table_name || ' TO read';
 END LOOP;
END;
/

The above query will
Note: The above PL/SQL can be executed either by a user with dba privilege or the owner of the schema (provided the user has permission to execute), in which case one can use SELECT * FROM USER_TABLES which will list only the tables belonging to the current logged in user.

Step 3: Optional
The below mentioned PL/SQL can be executed to create synonyms for all the tables and synonyms by logging in as dba used. Note that this will create a public synonym that is accessible to all users and might have some undesired effect. Skip this step and use Step 4 in case private synonyms have to be created for readonly user.


BEGIN
  FOR x IN (SELECT * FROM dba_tables WHERE owner='GTUSER')
  LOOP
    EXECUTE IMMEDIATE 'CREATE OR REPLACE SYNONYM ' || x.table_name ||' FOR ECECUSER.' || x.table_name || ' ';
  END LOOP;

  FOR x IN (SELECT * FROM dba_synonyms WHERE owner='GTUSER')
  LOOP
    EXECUTE IMMEDIATE 'CREATE OR REPLACE SYNONYM ' || x.synonym_name ||' FOR ECECUSER.' || x.synonym_name || ' ';
  END LOOP;
END;
/


Step 4.1:
Spool the create synonym (table and synonym from the target schema) query  into a file. The file would contain the create synonym script for all the tables and synonym which can be executed on the readonly user.
Login to GTUSER (user having the table for which synonym has to be created) or to a user having dba privelege and execute the queries mentioned.


set pagesize 1000;
set linesize 100;
set heading off;
set feedback off;
spool tablesynonym.sql
select 'CREATE OR REPLACE SYNONYM ' || table_name || ' FOR GTUSER.'||table_name ||';' from user_tables;
spool off;
spool synonym.sql
select 'CREATE OR REPLACE SYNONYM ' || synonym_name || ' FOR GTUSER.'||synonym_name||';' from user_synonyms;
spool off;


--Or select from dba_tables depending on the user access available
spool tablesynonym.sql
select 'CREATE OR REPLACE SYNONYM ' || table_name || ' FOR GTUSER.'||table_name ||';' from dba_tables where OWNER = 'GTUSER';
spool off;
spool synonym.sql
select 'CREATE OR REPLACE SYNONYM ' || synonym_name || ' FOR GTUSER.'||synonym_name ||';'from dba_synonyms where OWNER = 'GTUSER';
spool off;

Note:
1) Set pagesize can be set to value that is more than the number of tables in the schema
2) Set linesize can be set 100 or more to ensure that the output for each table is put into a single line.
3) Set heading to off so that the query name is not created.
4) Use either db_tables when you have dba priveledge else login into the user (say GTUSER) and use user_tables as all users usually can query this to get the tables belonging to them.

Step 4.2:
Login into readonly user and execute the spooled file>


@tablesynonym.sql
@synonym.sql

With the above we have covered the following:
1) Creating a read profile
2) Creating a readonly user
3) Granting select access on tables of a particular schema to read role.
4) Creating synoyms for all tables and synonyms of the main schema in readonly user profile.


Steps to drop an Oracle Database

The below commands in seqeunce can be used from a sqlplus prompt for dropping a database.

Step 1:
Set the Oracle SID to the instance to be dropped. This is important as this ensures that you connect to the correct instance.

export ORACLE_SID=<SID>
ex: $export ORACLE_SID=GTDB
Step 2:
Login to sqlplus as a Sysdba or connect to user with the dba privilege.

sqlplus "/as sysdba"
or
sqlplus dbauser/<pwd>
Step 3:
Execute the below commands in sequence.


startup mount;
alter system enable restricted session;
drop database;
This drops the selected instance of the database.

Tuesday, 11 March 2014

SOLVED: Proxy54 Error on Autowiring when AOP PointCut Matches Interface as Well as Impl Service

When using AOP pointcut with a regular expression to provide a transaction advice to all Beans ending with Service, problems can be encountered if the Service interface as well as the Service concrete class match the regular expression.

Point Cut Defined:
<aop:config>
            <aop:pointcut id="allServices" expression="bean(*Service)" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="allServices" />
</aop:config>
The above configuration will work without error as long as we do not have any Interface as well as its concrete class matching the regular expression. Autowiring issues will be faced when the Service interface and the the Service impl match the expression.

The Service Stack that can cause an issue is described below, only the class name has been mentioned for illustration (imports have been skipped). In the below design the Entity/Repository service followed a template pattern where all the concrete Repository Service extended from a template implementing the below service:
1) RepositoryService interface defining the basic Entity operations like, save, update, findByCritera
2) AbstractRepository interface where all the basic methods defined in the interface will be implemented.
3) ConcreteRepositoryService for each interface extending the AbstractRepositryService.

The interface that will be implemented by all Service

package com.gt.general.datajpa.service;
public interface RepositoryService <T AbstractEntity ,R extends JpaRepository <T,Long> &  QueryDslPredicateExecutor <T>> {
}

package com.gt.general.datajpa.serviceimpl;
@Service
public class TilesDefinitionService extends AbstractRepositoryService <AppConfig, AppConfigRepository> {
}


The problem is encountered when the Interface as well as the Impl class match the regular expression.
The reason for the issue is due to the way spring creates proxy as mentioned in the spring documentation (http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/aop-api.html#aop-pfb-proxy-types) Section (9.5.3 JDK- and CGLIB-based proxies). 
According to the documentation if an Interface Service is found the Proxy is created using JDK proxy which cannot proxy the concrete class.

Solution:
1)  Autowire interfaces instead of the concrete class, which would be the preferred approach as it gives the designer an option to change the service implementation without have to identify all classes referring the services.
2) Change the Name of the Interface so that it does not match the regular expression. In the above example changing RepositoryService and AbstractRepositoryService to say RepositryServiceInterface and AbstractRepositoryServiceInterface respectively.
3) Change the regular expression so that the interface is never matched. E.g bean(*impl*Service) which will ensure that only the implementation class is picked and hence all the proxies created are CGLIB proxies.
4) Change the regular Expression and all the Concrete Service class Names such that the regular expression can refer only to concrete classes.  Say bean(*ServiceImpl) and AppConfigService to AppConfigServiceImpl.
5) In case all the above cannot be changed force the advice to implement the proxy over the concrete class using “<aop:aspectj-autoproxy proxy-target-class="true"/>” in the spring context xml.

Errors:
Error observed when the Service is Autowired directly without setters

Error Class:

@Service
public class TilesViewService {

 private static final Logger logger = LoggerFactory.getLogger(AppConfigController.class);

 private final String wildCardSeparatorString = "/";
 private final String replaceString = "_";

 @Autowired
 TilesHeaderService tilesHeaderService;

 @Autowired
 TilesDefinitionService tilesDefinitionService;
 
 
 public void setTilesHeaderService(TilesHeaderService tilesHeaderService) {
  this.tilesHeaderService = tilesHeaderService;
 }

 
 public void setTilesDefinitionService(TilesDefinitionService tilesDefinitionService) {
  this.tilesDefinitionService = tilesDefinitionService;
 }
}


          Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.gt.general.datajpa.serviceimpl.TilesHeaderService com.gt.framework.common.service.TilesViewService.tilesHeaderService; nested exception is java.lang.IllegalArgumentException: Can not set com.gt.general.datajpa.serviceimpl.TilesHeaderService field com.gt.framework.common.service.TilesViewService.tilesHeaderService to $Proxy54
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
 at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
 ... 55 more
Caused by: java.lang.IllegalArgumentException: Can not set com.gt.general.datajpa.serviceimpl.TilesHeaderService field com.gt.framework.common.service.TilesViewService.tilesHeaderService to $Proxy54
 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
 at sun.reflect.UnsafeObjectFieldAccessorImpl.set(Unknown Source)
 at java.lang.reflect.Field.set(Unknown Source)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:513)
 ... 57 more



Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.gt.general.datajpa.serviceimpl.TilesHeaderService com.gt.framework.common.service.TilesViewService.tilesHeaderService; nested exception is java.lang.IllegalArgumentException: Can not set com.gt.general.datajpa.serviceimpl.TilesHeaderService field com.gt.framework.common.service.TilesViewService.tilesHeaderService to $Proxy54
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
            at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
            ... 55 more
Caused by: java.lang.IllegalArgumentException: Can not set com.gt.general.datajpa.serviceimpl.TilesHeaderService field com.gt.framework.common.service.TilesViewService.tilesHeaderService to $Proxy54
            at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
            at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
            at sun.reflect.UnsafeObjectFieldAccessorImpl.set(Unknown Source)
            at java.lang.reflect.Field.set(Unknown Source)
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:513)
            ... 57 more


Using a Setter in the services leads to a different error, which finally lead me to the actual problem

@Service
public class TilesViewService {

            private static final Logger logger = LoggerFactory.getLogger(AppConfigController.class);

            private final String wildCardSeparatorString = "/";
            private final String replaceString = "_";

           
            TilesHeaderService tilesHeaderService;

           
            TilesDefinitionService tilesDefinitionService;
           
            @Autowired
            public void setTilesHeaderService(TilesHeaderService tilesHeaderService) {
                        this.tilesHeaderService = tilesHeaderService;
            }

            @Autowired
            public void setTilesDefinitionService(TilesDefinitionService tilesDefinitionService) {
                        this.tilesDefinitionService = tilesDefinitionService;
            }
}
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.gt.framework.common.service.TilesViewService.setTilesHeaderService(com.gt.general.datajpa.serviceimpl.TilesHeaderService); nested exception is java.lang.IllegalArgumentException: argument type mismatch
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:604)
            at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
            ... 55 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:597)
            ... 57 more

SOLVED: JAXBException "The property or field ---- is annotated to be transient so can not be included in the proporder annotation".

Usecase:
Fixing the JAXBException "The property or field ---- is annotated to be transient so can not be included in the proporder annotation". 

Brief:
Recently, I was facing an issue with one of my REST services. On running the service all I could see were empty tags, although my service actually returned a list of employees.

Apart from this, on adding propOrder property, I kept hitting an exception "The property or field count is annotated to be transient so can not be included in the proporder annotation" at runtime, although none of my fields/methods were marked transient!!

After a long drill, the cause of both these problems was boiled down to the fact that I had a getter without a corresponding setter method!!!

Steps:

To demonstrate the problem and the solution thereafter, I have created a sample app EmpAppWithoutSetter.zip.
We will mainly focus on the EmployeeList.java class here.
The whole app is a simple Employee app which has all the CRUD operations, one of them being GET which returns all the employees and the number of employees.

If you run this app, you will find the below exception being logged in the console:

[Exception [EclipseLink-50009] (Eclipse Persistence Services - 2.4.1.v20120725-495bda0): org.eclipse.persistence.exceptions.JAXBException

Exception Description: The property or field count is annotated to be transient so can not be included in the proporder annotation.]

..............


If you look at the code, the field 'count' in EmployeeList.java has not been marked transient explicitly.

Also, just to play around a bit, remove the @XmlType annotation from EmployeeList.java class. Now, if you run the service, no exception occurs.
However, the XML structure will be as shown below:



            
Although there is an employee entry, the data is not shown at all. The reason for this is that in EmployeeList.java, we have getters for the fields 'list' and 'count'. However, we do not have their corresponding setter methods.
The exception thrown in the first case and an emplty list being displayed in the second case are each correct behaviour.
For more details, refer the EclipseLink bug.
Any one of the below three approaches can be used to fix the issue:
Approach 1:
Mark the fields public.
For example, in our case, we would need to declare our fields as below:
    public List<Employee> list = new ArrayList<Employee>();  
    public int count;
However, this is not the best approach, as marking fields public unnecessarily is quite unadvisable.
Approach 2: 
Create a setter method for every getter method that you have.
In our example, we would need to create setter methods corresponding to the getter methods, getList() and getCount(), as below:
    public void setList(List<Employee> list) {
        this.list = list;
    }

    public void setCount(int count) {
        this.count = count;
    }
Approach 3:
Add the annotation @XmlElement on top of the stand alone getter methods.
In this example, add it as shown:
   @XmlElement
    public List<Employee> getList() {
        return list;
    }
   
    @XmlElement
    public int getCount() {
        return count;
        }
The same three approaches hold good if you have setters without correponding getters.
On applying one of the above approaches and running the service, you should be able to get the required output.




Saturday, 1 March 2014

Customization support in REST Proxy


Usecase:
Using customization in JDeveloper for a REST proxy.

Pre-requisites:
Use JDeveloper 12c version along with Integrated weblogic server.

A Brief Intro:
JAXB forms an integral part of REST based services.
Customization mainly gives the power to control the names of the package and class names generated by JAXB. There may be various reasons why you might want to use customization in your REST service, one of them being the package and classes generated by the JAXB compiler may not be meaningful.
In my case, on running a REST proxy, I was facing the unmarshall exception as below:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"something"). Expected elements are <...>,<...>
One solution to this problem is to associate name attribute with XmlRootElement. Although this approach does solve the problem, due to some constraints, I could not stick to using this. Also, as I wanted to explore on the customization front, I took up the customization approach.

Steps:
In this blog, I have used a simple app CustomizationSample.zip to demonstrate customization in REST proxy. This app contains a REST service in EmployeeService.java, whose methods we shall invoke using the REST proxy. The application zip also contains the customization file. However, you could create a customization file on your own and place it anywhere wirthin your file system.

The customization file customizationFile.xml is as below. The inline comments indicate what this file does.


<?xml version="1.0" encoding="UTF-8"?>
<!-- This is the customization file for the schema employee.xsd-->
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.0" 
schemaLocation="http://localhost:7101/CustomizationSample-Project1-context-root/resources/application.wadl/xsd0.xsd" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns="http://www.example.org">
   <!-- This tells JAXB that the classes generated by it must be placed 
                        in the package with name myCustomizedPack-->
    <jaxb:schemaBindings>
        <jaxb:package name="myCustomizedPack"/>
    </jaxb:schemaBindings>
    
   <!-- This tells JAXB that the class for 'employeeList' complexType 
                           must be generated with name AllEmps-->    
    
    <jaxb:bindings node="xsd:complexType[@name='employeeList']">
        <jaxb:class name="AllEmps" />
    </jaxb:bindings>
 
    <!-- This tells JAXB that the element with name 'name' must be 
                        replaced with empName in JAXB class-->    
   
    <jaxb:bindings node="//xsd:element[@name='name']">
        <jaxb:property name="empName" />
    </jaxb:bindings>
</jaxb:bindings>

The most important part in this file wrt proxy is the schemaLocation. You can observe that the schemaLocation in my case was  http://localhost:7101/CustomizationSample-Project1-context-root/resources/application.wadl/xsd0.xsd 
To get the location, run the service. Append the generated WADL URL with xsd0.xsd. This schema is generated automatically for you by JDevelopr. Use this schemaLocation in your customization file.





Now you are all set to use this customization file in the REST proxy.
Create a new custom application, say CustomizationProxy. Invoke the REST client wizard. In the 'Create REST Proxy Client' wizard, supply the WADL URL and click on Customization Files. 

Locate the customization file by clicking on Add File in the 'Customization Files' pop up. Finally, click on Finish in REST Proxy Client wizard.



You can now observe that the JAXB classes are generated according to the customization file. Instead of the default 'generated' package, the package 'myCustomizedPack' is created as mentioned in the customization file. 




To invoke the methods of the service, you can now write a main method as below:
  public static void main(String[] args) {
        Client client = Localhost_CustomizationSampleProject1ContextRootResources.createClient();
        Localhost_CustomizationSampleProject1ContextRootResources.Project1 localhost_customizationsampleproject1contextrootresourcesproject1 =
        Localhost_CustomizationSampleProject1ContextRootResources.project1(client);
        // add your code here
        AllEmps allEmps = localhost_customizationsampleproject1contextrootresourcesproject1.getAsAllEmps();
        System.out.println("Number of emps:"+allEmps.getLists().size());
        System.out.println("Emp1 Name:"+allEmps.getLists().get(0).getEmpName());
    }

Here, if you observe, AllEmps was the name we assigned for EmployeeList class. Had we not used customization, the structure of the proxy would look as shown below:



Here, we can see that by default JAXB has generated a package by name 'generated' and the class names have been picked from the class names of the service. In this case, the main method would have a body as shown: 

    public static void main(String[] args) {
        Client client = Localhost_CustomizationSampleProject1ContextRootResources.createClient();
        Localhost_CustomizationSampleProject1ContextRootResources.Project1 localhost_customizationsampleproject1contextrootresourcesproject1 =
            Localhost_CustomizationSampleProject1ContextRootResources.project1(client);
        // add your code here
        EmployeeList allEmps = localhost_customizationsampleproject1contextrootresourcesproject1.getAsEmployeeList();
        System.out.println("Number of emps:"+allEmps.getLists().size());
        System.out.println("Emp1 Name:"+allEmps.getLists().get(0).getName());
    }
Thus, to conclude, customization gives us the flexibility to name the packages, classes and elements within these classes as per our requirements.