I'm new to soft. engineering and doing a project for user management and inside of Security package, I have a class called SecurityAspects where I define #Pointcut and #Around.
I'm using Apache Ant to compile the whole program.
SecurityAspects.java
package teste.servicepack.security.logic;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import teste.domain.UserSession;
import teste.servicepack.security.SecurityContextProvider;
import teste.servicepack.security.logic.Exception.FailRoleException;
import teste.servicepack.security.logic.Exception.NotAuthenticatedException;
import teste.servicepack.security.logic.Permission.HasRole;
import teste.utils.HibernateUtils;
import java.util.Arrays;
import java.util.logging.Logger;
#Aspect
public class SecurityAspects {
private static final Logger logger = Logger.getLogger(String.valueOf(SecurityAspects.class));
#Pointcut("#annotation(Transaction)")
public void TransactionPointCut(){}
#Pointcut("#annotation(IsAuthenticated)")
public void isAuthenticatedPointCut(){}
#Pointcut("#annotation(hasRole)")
public void hasRolePointCut(HasRole hasRole){}
#Pointcut("execution(* *(..))")
public void executionPointCut(){}
//Transaction
#Around("TransactionPointCut() && executionPointCut()")
public Object transactionAdvise(ProceedingJoinPoint pjp) throws Throwable{
HibernateUtils.getCurrentSession().beginTransaction();
try {
Object obj = pjp.proceed();
HibernateUtils.getCurrentSession().getTransaction().commit();
logger.info("Transaction finished successfully!");
return obj;
}catch (Exception e){
HibernateUtils.getCurrentSession().getTransaction().rollback();
throw e;
}
}
// isAuthenticated
#Around("isAuthenticatedPointCut() && executionPointCut()")
public Object isAuthenticatedAdvise(ProceedingJoinPoint pjp) throws Throwable
{
logger.info("isAuthenticated");
String cookie = SecurityContextProvider.getInstance().getSecuritySessionContext().getRequester();
UserSession session = (UserSession) HibernateUtils.getCurrentSession().load(UserSession.class,cookie);
if(session.getUser() != null)
return pjp.proceed();
throw new NotAuthenticatedException("Access Denied, not authenticated at " + pjp.getSourceLocation().getFileName() + " " + pjp.getSourceLocation().getLine() + " service: " + pjp.getSignature().getName());
}
// HasRole
#Around("hasRolePointCut(hasRole) && executionPointCut()")
public Object hasRoleAdvise(ProceedingJoinPoint pjp,HasRole hasRole) throws Throwable
{
logger.info("hasRole");
String cookie = SecurityContextProvider.getInstance().getSecuritySessionContext().getRequester();
UserSession session = (UserSession) HibernateUtils.getCurrentSession().load(UserSession.class,cookie);
String[] rolesIn = hasRole.role().split(",");
String[] roles = session.getUser().getRoles().split(",");
for(String checkRole: rolesIn){
if(Arrays.asList(roles).contains(checkRole)) {
return pjp.proceed();
}
}
throw new FailRoleException("Access Denied, does not have role " + hasRole.role() + " at " + pjp.getSourceLocation().getFileName() + " " + pjp.getSourceLocation().getLine() + " service: " + pjp.getSignature().getName());
}
}
build.xml
<?xml version="1.0"?>
<project default="deploy" basedir=".">
<property file="local.properties"/>
<property file="build.properties"/>
<path id="pathref">
<fileset dir="lib/hibernate">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/mysql">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/commons">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/log4j">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/json">
<include name="*.jar"/>
</fileset>
<fileset dir="${TOMCAT_HOME}/lib">
<include name="servlet-api.jar"/>
</fileset>
</path>
<taskdef name="hibernatetool"
classname="org.hibernate.tool.ant.HibernateToolTask"
classpathref="pathref" classpath="${build.dir.classes}"/>
<taskdef name="schemaupdate"
classname="org.hibernate.tool.hbm2ddl.SchemaUpdateTask"
classpathref="pathref" classpath="${build.dir.classes}"/>
<target name="generateUpdateHibernateSql" depends="compile">
<schemaupdate
properties="${build.dir.classes}/teste/domain/jdbc.properties"
quiet="no"
text="no">
<fileset dir="src/java">
<include name="**/*.hbm.xml"/>
</fileset>
</schemaupdate>
</target>
<target name="generateHibernateDomainObjects">
<mkdir dir="src/gen"/>
<replace dir="src/java" value="">
<include name="**/*.hbm.xml"/>
<replacefilter token='<timestamp source="db"' value="<timestamp"/>
</replace>
<hibernatetool>
<configuration>
<fileset dir="src/java">
<include name="**/*.hbm.xml"/>
</fileset>
</configuration>
<hbm2java
jdk5="true"
ejb3="false"
destdir="src/gen"/>
</hibernatetool>
<delete>
<fileset dir="src/gen">
<include name="**/*Impl.java"/>
</fileset>
</delete>
<replace dir="src/java" value="">
<include name="**/*.hbm.xml"/>
<replacefilter token='<timestamp' value='<timestamp source="db"'/>
</replace>
</target>
<target name="initDirs">
<mkdir dir="build"/>
<mkdir dir="build/ant"/>
<mkdir dir="build/ant/classes"/>
<mkdir dir="build/ant/war"/>
<mkdir dir="build/ant/war/WEB-INF"/>
<mkdir dir="build/ant/war/WEB-INF/classes"/>
<mkdir dir="build/ant/war/WEB-INF/lib"/>
</target>
<target name="deploy" depends="build.war">
<copy todir="${TOMCAT_HOME}/webapps/">
<fileset dir="build/ant/">
<include name="war/**/*.*"/>
</fileset>
</copy>
<touch file="${TOMCAT_HOME}/webapps/war/WEB-INF/web.xml"/>
</target>
<target name="build.war" depends="compile">
<copy todir="build/ant/war/WEB-INF" file="conf/web.xml"/>
<copy todir="build/ant/war">
<fileset dir="src/web">
<include name="**/*.*"/>
</fileset>
</copy>
<copy todir="build/ant/war/WEB-INF/classes">
<fileset dir="build/ant/classes">
<include name="**/*.*"/>
</fileset>
</copy>
<copy todir="build/ant/war/WEB-INF/lib">
<fileset dir="lib/hibernate">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/mysql">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/log4j">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/commons">
<include name="*.jar"/>
</fileset>
<fileset dir="lib/json">
<include name="*.jar"/>
</fileset>
</copy>
<touch file="build/ant/war/WEB-INF/web.xml"/>
</target>
<target name="war" depends="build.war">
<war file="build/ant/war.war">
<fileset dir="build/ant/war">
<include name="**/*.*"/>
</fileset>
</war>
</target>
<target name="compile" depends="initDirs">
<javac destdir="build/ant/classes"
debug="true"
encoding="UTF-8"
source="1.8" target="1.8"
classpathref="pathref">
<src path="src/java"/>
<src path="src/gen"/>
</javac>
<copy file="conf/log4j.properties" todir="build/ant/classes"/>
<copy file="conf/hibernate.cfg.xml" todir="build/ant/classes/teste/domain"/>
<copy todir="build/ant/classes">
<fileset dir="src/java">
<include name="**/*.xml"/>
</fileset>
</copy>
<copy file="conf/jdbc.properties" todir="${build.dir.classes}/teste/domain"/>
<replace file="${build.dir.classes}/teste/domain/jdbc.properties">
<replacefilter token="#database.username#" value="${database.username}"/>
<replacefilter token="#database.password#" value="${database.password}"/>
<replacefilter token="#database.connection.url#" value="${database.connection.url}"/>
</replace>
<replace file="${build.dir.classes}/teste/domain/hibernate.cfg.xml">
<replacefilter token="#database.username#" value="${database.username}"/>
<replacefilter token="#database.password#" value="${database.password}"/>
<replacefilter token="#database.connection.url#" value="${database.connection.url}"/>
<replacefilter token="#hibernate.show.sql#" value="${hibernate.show.sql}"/>
</replace>
</target>
</project>
But my problem is, when I try to compile with Ant, I have this error:
/Users/dilantaskin/Downloads/TrabalhoES/src/java/teste/servicepack/security/logic/SecurityAspects.java:3: error: package org.aspectj.lang does not exist
/Users/dilantaskin/Downloads/TrabalhoES/src/java/teste/servicepack/security/logic/SecurityAspects.java:4: error: package org.aspectj.lang.annotation does not exist
Like that I have over 20 errors just because of org.aspectj.lang.
In ide, everything looks fine, nothing stays red like it doesn't support.
I can see that I have aspectjrt.jar and aspectj-1.9.7 inside of External Libraries.
I tried to change the org.aspectj.lang to org.aspectj.lang3 but it doesn't recognize.
Can anyone explain me why do I get errors even though I have necessary jars?
INFO: Im not using Maven and I think(?) neither Spring. I have a basic Java project on IntelliJ using Tomcat, Hibernate, Servlet and Ant.
Edit by kriegaex: The author shared an MCVE on GitHub under Edifie/user-management-NF, making the problem reproducible (if first you also download and unzip Tomcat, then point the Ant build to it).
I inspected your project on GitHub, thanks for the link. There is so much wrong with it, I hardly know where to begin:
You committed library JARs instead of doing proper dependency management using Maven, Gradle or, if you insist to stay on Ant, something like Ivy. Dependencies should be downloaded during the build, not committed into a source code management (SCM) repository. Using Maven or Gradle also would have the advantage that IDEs like IntelliJ IDEA or Eclipse can automatically import your projects and also know where to find the dependencies and share them between projects, instead of you redundantly committing them to each of your project SCM repositories and manually adding them to your IDE project configuration. That is just ugly.
One of the JARs in your project is aspectj-1.9.6.jar. This is not what you want but an executable installer, the purpose of which is to install AspectJ locally. In there, you also find nested JARs such as aspectjrt.jar (runtime), aspectjtools.jar (compiler), aspectjweaver.jar (load-time weaving agent). You would have to execute that installer and then copy the libraries you need to your lib directory.
In order for the Java compiler to recognise your AspectJ imports, you need the AspectJ runtime on your classpath, i.e. you can download aspectjrt-1.9.6.jar from Maven Central (select "Downloads → jar" in the top right menu). Then you simply copy it to lib and add this to your Ant script:
<fileset dir="lib">
<include name="aspectjrt*.jar"/>
</fileset>
Now the project compiles, but if that achieves what you want depends on whether you want to use Spring AOP or native AspectJ. For the former, no AspectJ compiler is necessary, but your aspects would have to be made Spring components. For the latter, compiling with javac is not enough, you need the AspectJ compiler ajc. AspectJ provides its own Ant task for that. If you need the Ant task, you also want to have the AspectJ compiler on that task's classpath (not on the application classpath, only during build time). That would be aspectjtools-1.9.6.jar.
I am not an Ant user, so I have zero interest in this ancient build tool, but if you are an Ant user, you will know how to finish the job.
There is more wrong with your application, e.g. like I said in my comment, #annotation(Transaction) and #annotation(IsAuthenticated) should use fully qualified class names or import the classes and bind the annotations to pointcut parameters, if that is what you need.
I think, you should take a break and learn some Ant and AspectJ basics first, probably also Git basics. Or if you have a choice to switch from Ant to Maven, I strongly advise you to do that and forget Ant. If you are stuck with Ant because your employer requires you to use it, my sincere condolences. But actually, it is just a tool, and if you need it, just learn how to handle it. 🙂
P.S.: The current version of AspectJ is 1.9.8. If you like, you can upgrade.
Related
I have a Java application with Sprint framework. All the pages are accessed by a Controller which process the request and return a jps ModelAndView with several params to render in the JSP file.
Do you know any way to precompile these JSP files? I'm able to generate the *_jsp.java files using this ant script but I'm getting compilation errors trying to compile to .class like this one:
symbol: method getELContext()
location: variable _jspx_page_context of type PageContext
/home/user/apache-tomcat-8.5.14/webapps/project/WEB-INF/src/org/apache/jsp/WEB_002dINF/views/awarding/awarding_005finput/detail/applicant/awardingInputDetailApplicant_jsp.java:683: error: cannot find symbol
_jspx_th_c_005fset_005f5.setValue(new org.apache.jasper.el.JspValueExpression("/WEB-INF/views/awarding/awarding_input/detail/applicant/awardingInputDetailApplicant.jsp(68,5) '${!applicant.hasAnyConfirmedCandidacyGoal()}'",_jsp_getExpressionFactory().createValueExpression(_jspx_page_context.getELContext(),"${!applicant.hasAnyConfirmedCandidacyGoal()}",java.lang.Object.class)).getValue(_jspx_page_context.getELContext()));
All errors are regarding to "symbol: method getELContext()" ...
Update
This is the Ant task I'm using to compile the jsp from the *_jsp.java generated by the jasper task:
<target name="compileJSPs">
<mkdir dir="${tomcat.home}/work/Catalina/localhost/${project.name}/WEB-INF/classes"/>
<mkdir dir="${tomcat.home}/work/Catalina/localhost/${project.name}/WEB-INF/lib"/>
<javac destdir="${tomcat.home}/work/Catalina/localhost/${project.name}/WEB-INF/classes"
optimize="off"
debug="on" failonerror="false"
srcdir="${webapp.path}/WEB-INF/src"
excludes="**/*.smap">
<classpath>
<pathelement location="${webapp.path}/WEB-INF/classes"/>
<fileset dir="${webapp.path}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="${tomcat.home}/lib"/>
<fileset dir="${tomcat.home}/lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${tomcat.home}/bin">
<include name="*.jar"/>
</fileset>
</classpath>
<include name="**"/>
<exclude name="tags/**"/>
</javac>
</target>
Here I attach my tomcat_home/lib contain:
I am trying to compile an adroid project using ant which contains multiple sources and external 3rd party jars.
It works fine with eclipse but i require it to run through command line using ant.
my custom_rules.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?> <project name="CustomRules">
<target name="-pre-build" >
<copy todir="tmp-src" >
<fileset dir="src" includes="**" />
<fileset dir="talkAndroid" includes="**" />
<fileset dir="commonAndroid" includes="**" />
<fileset dir="cocos2dAndroid" includes="**" />
</copy>
<classpath id="classpath" description="The default classpath.">
<pathelement path="${classpath}"/>
<fileset dir="external_libs">
<include name="*.jar"/>
</fileset>
</classpath>
</target>
<target name="-post-build" >
<delete dir="tmp-src" />
</target> </project>
it isn't working for external_libs and unable to find external libraries, if I copy these jars from external_libs to libs folder ... duplicate class found errors are generated!
What should I do?
I have a tree like this
path/a
path/b
path/c
path/d/da
path/d/db
path/d/dc
Now in my javac task i want to
Compile everything in path/
Exclude everything in path/d/
Compile everything in path/d/db/
Like this:
path/a
path/b
path/c
path/d/db
I played with include/exclude and patternset but i couldn't achieve what i need.
Is there a way to do this?
The <difference> and <union> set operations will be handy for what you need.
The following Ant script shows how to combine several <fileset> elements into one:
<project name="ant-javac-include-and-exclude" default="run" basedir=".">
<target name="run">
<fileset id="all-files" dir="path">
<include name="**"/>
</fileset>
<fileset id="files-under-d" dir="path">
<include name="d/**"/>
</fileset>
<fileset id="files-under-d-db" dir="path">
<include name="d/db/**"/>
</fileset>
<!-- Matches all files under a, b, c -->
<difference id="all-files-NOT-under-d">
<fileset refid="all-files"/>
<fileset refid="files-under-d"/>
</difference>
<!-- Combine all files under a, b, c and under d/db -->
<union id="files-to-compile">
<difference refid="all-files-NOT-under-d"/>
<fileset refid="files-under-d-db"/>
</union>
<!-- Convert the absolute paths in "files-to-compile" to relative-->
<!-- paths. Also, "includes" of <javac> requires a comma-separated -->
<!-- list of files. -->
<pathconvert property="union-path" pathsep=",">
<union refid="files-to-compile"/>
<map from="${basedir}/" to=""/>
</pathconvert>
<javac
srcdir="."
includes="${union-path}"
includeantruntime="false"
/>
</target>
</project>
The above steps can be combined into the following:
<pathconvert property="union-path" pathsep=",">
<union>
<difference>
<fileset dir="path">
<include name="**"/>
</fileset>
<fileset dir="path">
<include name="d/**"/>
</fileset>
</difference>
<fileset dir="path">
<include name="d/db/**"/>
</fileset>
</union>
<map from="${basedir}/" to=""/>
</pathconvert>
<javac
srcdir="."
includes="${union-path}"
includeantruntime="false"
/>
On Eclipse I create war files by using ant.
The issue is that in the war file isn't included the right mypropfile.properties.
The file is properly copied, but also if I use <eclipse.refreshLocal resource="projectdir" depth="infinite"/> the old file is included. I have to refresh manually the project.
For Ant I use the "Run in the same JRE as the workspace" option.
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" basedir=".">
<description>
My Project
</description>
<property name="workspace.dir" value="${basedir}/../../"/>
<property name="src" value="${basedir}/../src"/>
<property name="build" value="${basedir}/../build"/>
<property name="build.classes" value="${basedir}/../build/classes"/>
<property name="lib.dir" value="${basedir}/WEB-INF/lib"/>
<property name="web.dir" value="${basedir}/WEB-INF"/>
<property environment="env"/>
<property name="real.dir" value="${basedir}/real"/>
<property name="real2.dir" value="${basedir}/real2"/>
<path id="classpath.server">
<fileset dir="${env.CATALINA_HOME}/lib" includes="*.jar"/>
<pathelement path="${build.classes}"/>
</path>
<path id="classpath.app">
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>
<target name="refreshResource" if="eclipse.refreshLocal">
<eclipse.refreshLocal resource="projectdir" depth="infinite"/>
</target>
<target name="clean">
<delete dir="${build}/classes"/>
<delete dir="${build}"/>
</target>
<target name="init" depends="clean, refreshResource">
<tstamp/>
<mkdir dir="${build}"/>
<mkdir dir="${build}/classes"/>
</target>
<target name="compile" depends="init">
<javac encoding="UTF8" srcdir="${src}" destdir="${build}/classes" includeantruntime="false">
<compilerarg value="-Xlint:unchecked"/>
<classpath>
<path refid="classpath.server.bin"/>
</classpath>
<classpath>
<path refid="classpath.server"/>
</classpath>
<classpath>
<path refid="classpath.app"/>
<fileset dir="${lib.dir}" includes="*.jar"/>
</classpath>
</javac>
</target>
<target name="deleteConfig">
<delete file="${src}/mypropfile.properties"/>
</target>
<target name="real" depends="deleteConfig">
<copy file="${real.dir}/realprop.properties" tofile="${src}/mypropfile.properties"/>
</target>
<target name="real2" depends="deleteConfig">
<copy file="${real2.dir}/real2prop.properties" tofile="${src}/mypropfile.properties"/>
</target>
<target name="war-real" depends="real, compile">
<input message="Warname (without .war):" addproperty="warname"/>
<war destfile="${workspace.dir}/${warname}.war" webxml="${web.dir}/web.xml">
<fileset dir="${basedir}">
<include name="**/*.*"/>
</fileset>
<classes dir="${build.classes}"/>
</war>
</target>
<target name="war-real2" depends="real2, compile">
<input message="Warname (without .war):" addproperty="warname"/>
<war destfile="${workspace.dir}/${warname}.war" webxml="${web.dir}/web.xml">
<fileset dir="${basedir}">
<include name="**/*.*"/>
</fileset>
<classes dir="${build.classes}"/>
</war>
</target>
EDIT
The target clean was wrong, so I've corrected it, but now build failed with error
BUILD FAILED ... Reference classpath.server.bin not found.
Ant doesn't care if Eclipse has refreshed the file or not. eclipse.refreshLocal is only relevant for editors and compilers inside of the IDE.
When you run the Ant build.xml, Ant copies the file in question in the real target into the source folder and compile copies it into ${build}/classes (at least it should do that). So before you create the WAR, you must make sure the compile step has done its work (i.e. look into each file to make sure that a change is visible in each copy).
What worries my is that you use different ways to access the classes:
${build}/classes
${build.classes}
${basedir}/../build/classes
So the first step should be to define a single way to locate the folder and then use this pattern everywhere.
If that doesn't solve your problem, you need to make sure Ant notices that the file has changed. Old filesystems like FAT support only timestamps which have second resolution. If you use an USB stick for your sources, it's possible to change the file and run Ant so fast that Ant thinks the file hasn't changed.
Lastly, you need to check your classpath. If one of the JAR dependencies also contains a file called mypropfile.properties, then Java resource loading can find either version.
This and other problems made me use a different solution to configure WAR files: I pass a system property with the absolute path of the config file. That way, the WAR file doesn't change when the config changes and I have full control over which config file is loaded.
I'm using Ant to build my Java application and to generate the MANIFEST.MF file automatically so it includes all the jars in my lib directory.
This seems to work but the problem is that instead of writing them as lib/some.jar, it includes my Eclipse project's name: MyProject/lib/some.jar.
This is ofcourse incorrect and causes none of the jars to be found when run as a standalone app.
Build.xml (important part is at the end):
<?xml version="1.0"?>
<project name="fidea_migration" default="dist">
<path id="compile.classpath">
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
</path>
<target name="clean" description="cleaning the old deliverables">
<delete includeemptydirs="true">
<fileset dir="bin" includes="**/*"/>
</delete>
<delete includeemptydirs="true">
<fileset dir="_deliverables" includes="**/*"/>
</delete>
</target>
<target name="prepare" description="preparing the deliverables folders">
<mkdir dir="_deliverables/lib"/>
</target>
<path id="jarlib">
<fileset dir="lib/">
<include name="**/*.jar"/>
</fileset>
</path>
<manifestclasspath property="lib.list" jarfile=".">
<classpath refid="jarlib" />
</manifestclasspath>
<target name="compile" depends="clean, prepare" description="compiling java sources">
<mkdir dir="bin"/>
<javac srcdir="src/main/java" destdir="bin">
<classpath refid="compile.classpath"/>
</javac>
</target>
<target name="dist" depends="compile" description="creating binary distribution">
<copy todir="_deliverables/lib">
<fileset dir="lib"/>
</copy>
<copy todir="_deliverables">
<fileset dir="src/main/resources">
</fileset>
</copy>
<jar jarfile="_deliverables/lib/app.jar" basedir="bin">
<manifest>
<attribute name="Class-Path" value="${lib.list}"/>
</manifest>
</jar>
</target>
</project>
Example of how my Manifest looks:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.4
Class-Path: MyProject/lib/All-MB.jar MyProject/lib/activation.jar MyProject/lib/aspectjrt.jar
Any idea on how to fix this so it just shows xxx.jar instead of MyProject/lib/xxx.jar (so without "MyProject/lib/")?
Cheers,
Bart
manifestclasspath expects the jarfile attribute to point to the location of the JAR file (which probably doesn't exist yet, but that's fine). Since you're creating the JAR file at _deliverables/lib/app.jar and you're also copying all the lib JARs from lib to _deliverables/lib then
<manifestclasspath property="lib.list" jarfile="lib/app.jar">
<classpath refid="jarlib" />
</manifestclasspath>
should do the trick, and will create an eventual Class-Path with the right relative paths, i.e. All-MB.jar activation.jar aspectjrt.jar etc. etc.
You must set your project Dir inside your build.xml as,
<property name="projectDir" value=".." />
After this, you must try to work on everything with relative path. Currently, the reason behind problem is that the absolute path is being used.