Refactoring and simplification of communication with rest API.

This commit is contained in:
Niklas Herder 2012-04-02 12:29:56 +02:00
parent 3a4ad9179c
commit f162037a5e
9 changed files with 499 additions and 524 deletions

@ -161,7 +161,6 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- JPA --> <!-- JPA -->
<!-- Hibernate impl --> <!-- Hibernate impl -->
<dependency> <dependency>
@ -321,6 +320,11 @@
<artifactId>wicket-components</artifactId> <artifactId>wicket-components</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.10</version>
</dependency>
</dependencies> </dependencies>
@ -471,6 +475,7 @@
<org.springframework.version>3.0.5.RELEASE</org.springframework.version> <org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<org.springframework.data.version>1.0.3.RELEASE</org.springframework.data.version> <org.springframework.data.version>1.0.3.RELEASE</org.springframework.data.version>
<querydsl.version>2.3.3</querydsl.version> <querydsl.version>2.3.3</querydsl.version>
<remote.lookup.url>https://api.dsv.su.se/rest</remote.lookup.url>
</properties> </properties>
<profiles> <profiles>
@ -494,6 +499,7 @@
<database.showSql>true</database.showSql> <database.showSql>true</database.showSql>
<database.generateDdl>true</database.generateDdl> <database.generateDdl>true</database.generateDdl>
<wicket.mode>deployment</wicket.mode> <wicket.mode>deployment</wicket.mode>
<remote.lookup.url>http://apitest.dsv.su.se:8080/rest</remote.lookup.url>
</properties> </properties>
</profile> </profile>
<profile> <profile>
@ -505,6 +511,7 @@
<database.showSql>false</database.showSql> <database.showSql>false</database.showSql>
<database.generateDdl>false</database.generateDdl> <database.generateDdl>false</database.generateDdl>
<wicket.mode>deployment</wicket.mode> <wicket.mode>deployment</wicket.mode>
<remote.lookup.url>https://api.dsv.su.se/rest</remote.lookup.url>
</properties> </properties>
</profile> </profile>
</profiles> </profiles>

@ -1,10 +1,8 @@
/** /**
* *
*/ */
package se.su.dsv.scipro.admin.panels; package se.su.dsv.scipro.admin.panels;
import java.io.Serializable;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.CheckBox;
@ -13,16 +11,16 @@ import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean; import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.context.annotation.ImportResource;
import se.su.dsv.scipro.ApplicationSettings; import se.su.dsv.scipro.ApplicationSettings;
import se.su.dsv.scipro.io.ExternalImporter; import se.su.dsv.scipro.io.ExternalImporter;
import se.su.dsv.scipro.io.exceptions.ExternalImportException; import se.su.dsv.scipro.io.exceptions.ExternalImportException;
import se.su.dsv.scipro.security.auth.roles.Roles; import se.su.dsv.scipro.security.auth.roles.Roles;
import java.io.Serializable;
public class ManualImportExportPanel extends Panel { public class ManualImportExportPanel extends Panel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Label statusMessage = new Label("statusMessage",""); private Label statusMessage = new Label("statusMessage", "");
@SpringBean @SpringBean
private ExternalImporter externalImporter; private ExternalImporter externalImporter;
@SpringBean @SpringBean
@ -31,25 +29,30 @@ public class ManualImportExportPanel extends Panel {
private ApplicationSettings applicationSettings; private ApplicationSettings applicationSettings;
private Form<ImportExportParams> importExportForm; private Form<ImportExportParams> importExportForm;
private static final Logger logger = Logger.getLogger(ManualImportExportPanel.class); private static final Logger logger = Logger.getLogger(ManualImportExportPanel.class);
public ManualImportExportPanel(String id) { public ManualImportExportPanel(String id) {
super(id); super(id);
init(); init();
} }
private void init(){
private void init() {
statusMessage.setOutputMarkupId(true); statusMessage.setOutputMarkupId(true);
if(hasRemote()) if (hasRemote()) {
setMessage("Using remote: "+getRemoteUrl()); setMessage("Using remote: " + getRemoteUrl());
else }
else {
setMessage("No remote configured"); setMessage("No remote configured");
}
add(statusMessage); add(statusMessage);
setupForm(); setupForm();
} }
private void setupForm(){
importExportForm = new Form<ImportExportParams>("importExportForm",new CompoundPropertyModel<ImportExportParams>(new ImportExportParams())){ private void setupForm() {
importExportForm = new Form<ImportExportParams>("importExportForm", new CompoundPropertyModel<ImportExportParams>(new ImportExportParams())) {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Override @Override
public void onSubmit(){ public void onSubmit() {
final ImportExportParams params = getModelObject(); final ImportExportParams params = getModelObject();
final String userNameIn = params.getImportUserName(); final String userNameIn = params.getImportUserName();
final long userIdIn = params.getImportUserId(); final long userIdIn = params.getImportUserId();
@ -60,78 +63,85 @@ public class ManualImportExportPanel extends Panel {
final String projectTitleIn = params.getImportProjectTitle(); final String projectTitleIn = params.getImportProjectTitle();
final long projectIdOut = params.getExportProjectId(); final long projectIdOut = params.getExportProjectId();
if(userNameIn != null && !userNameIn.equals("")){ if (userNameIn != null && !userNameIn.equals("")) {
logger.debug("Attempting remote import of user: "+userNameIn); logger.debug("Attempting remote import of user: " + userNameIn);
try{ try {
externalImporter.importUser(userNameIn,params.isIncludeLinkedProjects()); externalImporter.importUser(userNameIn, params.isIncludeLinkedProjects());
setMessage("Succesfully imported user with username: "+userNameIn + " from "+getRemoteUrl()); setMessage("Succesfully imported user with username: " + userNameIn + " from " + getRemoteUrl());
}catch(final ExternalImportException eie){ }
logger.warn("Caught error while importing user from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import user with username: "+userNameIn+ " from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing user from remote system: " + eie.getMessage());
setMessage("Failed to import user with username: " + userNameIn + " from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(userIdIn > 0){ if (userIdIn > 0) {
logger.debug("Attempting remote import of id: "+userIdIn); logger.debug("Attempting remote import of id: " + userIdIn);
try{ try {
externalImporter.importUser(userIdIn,params.isIncludeLinkedProjects()); externalImporter.importUser(userIdIn, params.isIncludeLinkedProjects());
setMessage("Succesfully imported user with id: "+userIdIn + " from "+getRemoteUrl()); setMessage("Succesfully imported user with id: " + userIdIn + " from " + getRemoteUrl());
}catch(final ExternalImportException eie){ }
logger.warn("Caught error while importing user from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import user with id: "+userIdIn+ " from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing user from remote system: " + eie.getMessage());
setMessage("Failed to import user with id: " + userIdIn + " from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(importSupervisors){ if (importSupervisors) {
logger.debug("Importing all listed supervisors"); logger.debug("Importing all listed supervisors");
try{ try {
externalImporter.importUsersOfRole(Roles.EMPLOYEE,params.isIncludeLinkedProjects()); externalImporter.importUsersOfRole(Roles.EMPLOYEE, params.isIncludeLinkedProjects());
setMessage("Successfully imported supervisors from " + getRemoteUrl()); setMessage("Successfully imported supervisors from " + getRemoteUrl());
}catch(final ExternalImportException eie){ }
logger.warn("Caught error while importing supervisors from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import supervisors from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing supervisors from remote system: " + eie.getMessage());
setMessage("Failed to import supervisors from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(importSupervisorUnits){ if (importSupervisorUnits) {
logger.debug("Importing attached units for supervisors"); logger.debug("Importing attached units for supervisors");
try { try {
externalImporter.importSupervisorUnits(); externalImporter.importSupervisorUnits();
setMessage("Successfully imported attached units to supervisors from " + getRemoteUrl()); setMessage("Successfully imported attached units to supervisors from " + getRemoteUrl());
} catch (final ExternalImportException eie) { }
logger.warn("Caught error while importing units to supervisors from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import units from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing units to supervisors from remote system: " + eie.getMessage());
setMessage("Failed to import units from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(importResearchAreas){ if (importResearchAreas) {
logger.debug("Importing all research areas from remote host"); logger.debug("Importing all research areas from remote host");
try { try {
externalImporter.importResearchAreas(); externalImporter.importResearchAreas();
setMessage("Successfully imported research areas from " + getRemoteUrl()); setMessage("Successfully imported research areas from " + getRemoteUrl());
} catch (final ExternalImportException eie){ }
logger.warn("Caught error while importing research areas from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import research areas from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing research areas from remote system: " + eie.getMessage());
setMessage("Failed to import research areas from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(projectIdIn > 0){ if (projectIdIn > 0) {
logger.debug("Attempting remote import of project: "+projectIdIn); logger.debug("Attempting remote import of project: " + projectIdIn);
try{ try {
externalImporter.importProject(projectIdIn); externalImporter.importProject(projectIdIn);
setMessage("Successfully imported project with id "+projectIdIn+" from " + getRemoteUrl()); setMessage("Successfully imported project with id " + projectIdIn + " from " + getRemoteUrl());
}catch (final ExternalImportException eie){ }
logger.warn("Caught error while importing project from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import project with id "+projectIdIn+" from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing project from remote system: " + eie.getMessage());
setMessage("Failed to import project with id " + projectIdIn + " from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(projectTitleIn != null && !projectTitleIn.equals((""))){ if (projectTitleIn != null && !projectTitleIn.equals((""))) {
logger.debug("Attempting remote import of projects matching: '"+projectTitleIn+"'"); logger.debug("Attempting remote import of projects matching: '" + projectTitleIn + "'");
try{ try {
externalImporter.importProjects(projectTitleIn); externalImporter.importProjects(projectTitleIn);
setMessage("Successfully imported all projects matching title '"+projectTitleIn+"' from " + getRemoteUrl()); setMessage("Successfully imported all projects matching title '" + projectTitleIn + "' from " + getRemoteUrl());
}catch (final ExternalImportException eie){ }
logger.warn("Caught error while importing project from remote system: "+eie.getMessage()); catch (final ExternalImportException eie) {
setMessage("Failed to import projects matching title '"+projectTitleIn+"' from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); logger.warn("Caught error while importing project from remote system: " + eie.getMessage());
setMessage("Failed to import projects matching title '" + projectTitleIn + "' from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode());
} }
} }
if(projectIdOut > 0){ if (projectIdOut > 0) {
logger.debug("Attempting remote export of project: "+projectIdOut); logger.debug("Attempting remote export of project: " + projectIdOut);
throw new UnsupportedOperationException("Not implemented yet"); throw new UnsupportedOperationException("Not implemented yet");
} }
} }
@ -148,17 +158,21 @@ public class ManualImportExportPanel extends Panel {
importExportForm.add(new CheckBox("importResearchAreas")); importExportForm.add(new CheckBox("importResearchAreas"));
importExportForm.setVisible(hasRemote()); importExportForm.setVisible(hasRemote());
} }
private boolean hasRemote(){
private boolean hasRemote() {
return externalImporter.supportsRemoteOperations(); return externalImporter.supportsRemoteOperations();
} }
private String getRemoteUrl(){
return applicationSettings.getRemoteLookupUrl(); private String getRemoteUrl() {
return externalImporter.getLookupUrl();
} }
private void setMessage(final String message){
private void setMessage(final String message) {
statusMessage.setDefaultModelObject(message); statusMessage.setDefaultModelObject(message);
} }
//Utility model-class //Utility model-class
private class ImportExportParams implements Serializable{ private class ImportExportParams implements Serializable {
private static final long serialVersionUID = 5961088002006031317L; private static final long serialVersionUID = 5961088002006031317L;
private String importUserName; private String importUserName;
private long importUserId; private long importUserId;
@ -168,58 +182,76 @@ public class ManualImportExportPanel extends Panel {
private long importProjectId; private long importProjectId;
private String importProjectTitle; private String importProjectTitle;
private long exportProjectId; private long exportProjectId;
private boolean includeLinkedProjects=false; private boolean includeLinkedProjects = false;
public String getImportUserName() { public String getImportUserName() {
return importUserName; return importUserName;
} }
public void setImportUserName(String importUserName) { public void setImportUserName(String importUserName) {
this.importUserName = importUserName; this.importUserName = importUserName;
} }
public long getImportProjectId() { public long getImportProjectId() {
return importProjectId; return importProjectId;
} }
public void setImportProjectId(long importProjectId) { public void setImportProjectId(long importProjectId) {
this.importProjectId = importProjectId; this.importProjectId = importProjectId;
} }
public String getImportProjectTitle() { public String getImportProjectTitle() {
return importProjectTitle; return importProjectTitle;
} }
public void setImportProjectTitle(String importProjectTitle) { public void setImportProjectTitle(String importProjectTitle) {
this.importProjectTitle = importProjectTitle; this.importProjectTitle = importProjectTitle;
} }
public long getExportProjectId() { public long getExportProjectId() {
return exportProjectId; return exportProjectId;
} }
public void setExportProjectId(long exportProjectId) { public void setExportProjectId(long exportProjectId) {
this.exportProjectId = exportProjectId; this.exportProjectId = exportProjectId;
} }
public boolean isImportSupervisors() { public boolean isImportSupervisors() {
return importSupervisors; return importSupervisors;
} }
public void setImportSupervisors(boolean importSupervisors) { public void setImportSupervisors(boolean importSupervisors) {
this.importSupervisors = importSupervisors; this.importSupervisors = importSupervisors;
} }
public boolean isImportSupervisorUnits() { public boolean isImportSupervisorUnits() {
return importSupervisorUnits; return importSupervisorUnits;
} }
public void setImportSupervisorUnits(boolean importSupervisorUnits) { public void setImportSupervisorUnits(boolean importSupervisorUnits) {
this.importSupervisorUnits = importSupervisorUnits; this.importSupervisorUnits = importSupervisorUnits;
} }
public long getImportUserId() { public long getImportUserId() {
return importUserId; return importUserId;
} }
public void setImportUserId(long importUserId) { public void setImportUserId(long importUserId) {
this.importUserId = importUserId; this.importUserId = importUserId;
} }
public boolean isIncludeLinkedProjects() { public boolean isIncludeLinkedProjects() {
return includeLinkedProjects; return includeLinkedProjects;
} }
public void setIncludeLinkedProjects(boolean includeLinkedProjects) { public void setIncludeLinkedProjects(boolean includeLinkedProjects) {
this.includeLinkedProjects = includeLinkedProjects; this.includeLinkedProjects = includeLinkedProjects;
} }
public void setImportResearchAreas(boolean importResearchAreas) { public void setImportResearchAreas(boolean importResearchAreas) {
this.importResearchAreas = importResearchAreas; this.importResearchAreas = importResearchAreas;
} }
public boolean isImportResearchAreas() { public boolean isImportResearchAreas() {
return importResearchAreas; return importResearchAreas;
} }

@ -7,12 +7,21 @@ import se.su.dsv.scipro.security.auth.roles.Roles;
* Specifies interaction of an importing service component. * Specifies interaction of an importing service component.
*/ */
public interface ExternalImporter { public interface ExternalImporter {
String getLookupUrl();
void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException; void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException;
void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException; void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException;
void importUsersOfRole(final Roles role,boolean includeLinkedEntities) throws ExternalImportException;
void importUsersOfRole(final Roles role, boolean includeLinkedEntities) throws ExternalImportException;
void importProject(final long externalIdentifier) throws ExternalImportException; void importProject(final long externalIdentifier) throws ExternalImportException;
void importProjects(final String matchingTitle) throws ExternalImportException; void importProjects(final String matchingTitle) throws ExternalImportException;
void importSupervisorUnits() throws ExternalImportException; void importSupervisorUnits() throws ExternalImportException;
void importResearchAreas() throws ExternalImportException; void importResearchAreas() throws ExternalImportException;
boolean supportsRemoteOperations(); boolean supportsRemoteOperations();
} }

@ -0,0 +1,79 @@
package se.su.dsv.scipro.io.http;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import org.apache.log4j.Logger;
import se.su.dsv.scipro.io.exceptions.HttpRemoteRespondedWithFailureException;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ApiClient {
public static final int CONN_TIMEOUT = 1000 * 60;
public static final int READ_TIMEOUT = 1000 * 120;
public static final String ENC_TYPE = "UTF8";
public enum REQUEST_TYPE {POST, GET}
private final Logger logger = Logger.getLogger(ApiClient.class);
private final Map<String, String> parameters = new HashMap<String, String>();
private String baseUrl;
private String user;
private String password;
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getBaseUrl() {
return baseUrl;
}
private ApiClient() {
}
public void setUser(String user) {
this.user = user;
}
public void setPassword(String password) {
this.password = password;
}
/**
* Start to process the request
*
* @throws IOException if a connection error occurred
*/
public void processRequest(String urlPath, DtoResponseHandler responseHandler, Map<String, String> parameters, REQUEST_TYPE requestType) throws HttpRemoteRespondedWithFailureException {
logger.debug("Sending remote request (" + requestType + "): " + urlPath + "?" + parameters);
try {
WebResource resource = new Client().resource(baseUrl + urlPath);
resource.addFilter(new HTTPBasicAuthFilter(user, password));
String result = null;
switch (requestType) {
case GET:
for (Map.Entry<String, String> stringStringEntry : parameters.entrySet()) {
resource = resource.queryParam(stringStringEntry.getKey(), stringStringEntry.getValue());
}
result = resource.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
break;
case POST:
result = resource.entity(parameters).accept(MediaType.APPLICATION_JSON).post(String.class);
}
responseHandler.handleResponse(result);
}
catch (UniformInterfaceException e) {
logger.error(e.getMessage(), e);
throw new HttpRemoteRespondedWithFailureException(e.getResponse().getStatus());
}
}
}

@ -1,152 +0,0 @@
package se.su.dsv.scipro.io.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import se.su.dsv.scipro.io.exceptions.HttpRemoteRespondedWithFailureException;
public class HttpRequestSender {
public static final int CONN_TIMEOUT = 1000*60;
public static final int READ_TIMEOUT = 1000*120;
public static final String ENC_TYPE = "UTF8";
public enum REQUEST_TYPE{POST,GET};
private final REQUEST_TYPE requestType;
private final Logger logger = Logger.getLogger(HttpRequestSender.class);
private final DtoResponseHandler responseHandler;
private final Map<String, String> parameters = new HashMap<String,String>();
private final String url;
private final String user;
private final String password;
public HttpRequestSender(final DtoResponseHandler responseHandler, final String url, final String user, final String password, final Map<String, String> parameters, final REQUEST_TYPE requestType){
if(responseHandler == null){
logger.error("Could not send request, no response handler was provided");
throw new IllegalArgumentException("You need to provide a handler for the response");
}
if(url == null){
logger.error("Can't create request for null url");
throw new IllegalArgumentException("url parameter must be non-null");
}
this.responseHandler = responseHandler;
this.url = url;
this.user = user;
this.password = password;
if(parameters!=null)
this.parameters.putAll(parameters);
this.requestType = requestType;
}
/**
* Start to process the request
* @throws IOException if a connection error occurred
*/
public void processRequest() throws IOException, HttpRemoteRespondedWithFailureException {
logger.debug("Sending remote request ("+requestType+"): " + url + "?"+parameters);
String parameterData = "";
int count = 0;
//Format request
for(Map.Entry<String, String> me : parameters.entrySet()){
if(count > 0){
parameterData += "&";
}
parameterData += me.getKey() + "=" + me.getValue();
count++;
}
//Add to request as appropriate
String urlString = url;
if(requestType == REQUEST_TYPE.GET && parameters.size() > 0){
urlString += "?" + parameterData;
}
HttpURLConnection conn = null;
OutputStreamWriter osr = null;
BufferedReader br = null;
try{
//This will throw an MalformedURLException if the url is not valid
URL u = new URL(urlString);
conn = (HttpURLConnection) getConnection(u);
conn.setRequestMethod(requestType.name());
//Set connection timeouts
conn.setConnectTimeout(CONN_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
if(user != null && password != null)
conn.setRequestProperty("Authorization", getBasicEncodedAuthData());
conn.setRequestProperty("Accept", getAcceptContentType());
//Handle POST-style requests
if(requestType == REQUEST_TYPE.POST){
conn.setDoOutput(true);
osr = new OutputStreamWriter(conn.getOutputStream());
osr.write(parameterData);
osr.flush();
}
//Handle response errors early on
if(conn.getResponseCode() != HttpServletResponse.SC_OK){
logger.error("Request URL: "+ u + " responded with failure, status code: " + conn.getResponseCode());
dispatchError(conn.getResponseCode());
}
br = new BufferedReader(new InputStreamReader(conn.getInputStream(),ENC_TYPE));
String line = "";
StringBuffer response = new StringBuffer();
while((line = br.readLine()) != null){
response.append(line);
}
responseHandler.handleResponse(response.toString());
}catch(final MalformedURLException mue){
logger.warn("Malformed url: " + urlString + " caused exception");
throw mue;
}catch(final SocketTimeoutException ste){
logger.warn("Socket timeout while talking to remote host on URL: " + urlString);
throw ste;
}catch(final UnknownHostException uhe){
logger.warn("Unknown host: " + urlString + " caused exception");
throw uhe;
}finally{
if(conn != null){
conn.disconnect();
}
if(osr != null){
try{
osr.close();
}catch(final IOException ioe){
logger.warn("Close on output stream caused an exception, not much to do about that");
}
}
if(br != null){
try{
br.close();
}catch(final IOException ioe){
logger.warn("Close on input stream caused an exception, not much to do about that");
}
}
}
}
private void dispatchError(int responseCode) {
throw new HttpRemoteRespondedWithFailureException(responseCode);
}
private String getBasicEncodedAuthData() {
String userpassword = user + ":" + password;
String encodedAuthorization = Base64.encodeBase64String(userpassword.getBytes());
return ("Basic "+encodedAuthorization);
}
private String getAcceptContentType() {
return "application/json";
}
protected HttpURLConnection getConnection(final URL url) throws IOException{
return (HttpURLConnection)url.openConnection();
}
}

@ -1,24 +0,0 @@
package se.su.dsv.scipro.io.http;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import org.apache.log4j.Logger;
public class HttpsRequestSender extends HttpRequestSender{
private Logger logger = Logger.getLogger(HttpsRequestSender.class);
public HttpsRequestSender(final DtoResponseHandler responseHandler, final String url, final String user, final String password, final Map<String, String> parameters, final REQUEST_TYPE requestType){
super(responseHandler,url,user,password,parameters,requestType);
}
@Override
protected HttpURLConnection getConnection(final URL url) throws IOException{
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
return con;
}
}

@ -1,44 +1,25 @@
package se.su.dsv.scipro.io.impl; package se.su.dsv.scipro.io.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import se.su.dsv.scipro.ApplicationSettings; import se.su.dsv.scipro.ApplicationSettings;
import se.su.dsv.scipro.data.dao.interfaces.ProjectDao; import se.su.dsv.scipro.data.dao.interfaces.ProjectDao;
import se.su.dsv.scipro.data.dao.interfaces.UserDao; import se.su.dsv.scipro.data.dao.interfaces.UserDao;
import se.su.dsv.scipro.data.dataobjects.Project; import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.User; import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.io.ExternalImporter; import se.su.dsv.scipro.io.ExternalImporter;
import se.su.dsv.scipro.io.dto.AbstractDtoResponseHandler; import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.io.dto.ProjectDTO;
import se.su.dsv.scipro.io.dto.ProjectDTOCollectionWrapper;
import se.su.dsv.scipro.io.dto.ProjectParticipantDTO;
import se.su.dsv.scipro.io.dto.ProjectParticipantDTOCollectionWrapper;
import se.su.dsv.scipro.io.dto.ResearchAreaDTO;
import se.su.dsv.scipro.io.dto.ResearchAreaDTOCollectionWrapper;
import se.su.dsv.scipro.io.dto.PersonDTO;
import se.su.dsv.scipro.io.dto.PersonDTOCollectionWrapper;
import se.su.dsv.scipro.io.dto.UnitDTO;
import se.su.dsv.scipro.io.dto.UnitDTOCollectionWrapper;
import se.su.dsv.scipro.io.dto.UserDTO;
import se.su.dsv.scipro.io.dto.UserDTOCollectionWrapper;
import se.su.dsv.scipro.io.dto.UserRoleDTO;
import se.su.dsv.scipro.io.dto.UsernameDTO;
import se.su.dsv.scipro.io.dto.UsernameDTOCollectionWrapper;
import se.su.dsv.scipro.io.exceptions.ExternalImportException; import se.su.dsv.scipro.io.exceptions.ExternalImportException;
import se.su.dsv.scipro.io.exceptions.HttpRemoteRespondedWithFailureException;
import se.su.dsv.scipro.io.facade.ImporterFacade; import se.su.dsv.scipro.io.facade.ImporterFacade;
import se.su.dsv.scipro.io.http.HttpRequestSender; import se.su.dsv.scipro.io.http.ApiClient;
import se.su.dsv.scipro.io.http.HttpsRequestSender;
import se.su.dsv.scipro.security.auth.roles.Roles; import se.su.dsv.scipro.security.auth.roles.Roles;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/** /**
* Importer implementation, uses standard HTTP requests and Json-wrappers. * Importer implementation, uses standard HTTP requests and Json-wrappers.
* To use this class as the importer, configure it via applicationContext.xml. * To use this class as the importer, configure it via applicationContext.xml.
@ -53,355 +34,383 @@ public class ExternalImporterDaisyImpl implements ExternalImporter {
@Autowired @Autowired
private ProjectDao projectDao; private ProjectDao projectDao;
private final Logger logger = Logger.getLogger(ExternalImporterDaisyImpl.class); private final Logger logger = Logger.getLogger(ExternalImporterDaisyImpl.class);
private ApiClient client;
public void setClient(ApiClient client) {
this.client = client;
}
public ApiClient getClient() {
return client;
}
@Override
public String getLookupUrl() {
return client.getBaseUrl();
}
@Override @Override
@Transactional @Transactional
public void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException{ public void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException {
final Map<String,String> parameters = new HashMap<String,String>(); final Map<String, String> parameters = new HashMap<String, String>();
final UserDTOPreProcessor userDTODecorator = getDefaultUserProcessor(includeLinkedEntities); final UserDTOPreProcessor userDTODecorator = getDefaultUserProcessor(includeLinkedEntities);
//parameters.put("showTheses", Boolean.valueOf(includeLinkedEntities).toString()); //parameters.put("showTheses", Boolean.valueOf(includeLinkedEntities).toString());
sendDefaultUserRequest(parameters,HttpRequestSender.REQUEST_TYPE.GET,userDTODecorator,new UrlProcessor(){ sendDefaultUserRequest(parameters, ApiClient.REQUEST_TYPE.GET, userDTODecorator, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/person/username/"+userName); return (url + "/person/username/" + userName);
} }
}); });
} }
@Override @Override
@Transactional @Transactional
public void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException{ public void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException {
final Map<String,String> parameters = new HashMap<String,String>(); final Map<String, String> parameters = new HashMap<String, String>();
final UserDTOPreProcessor userDTODecorator = getDefaultUserProcessor(includeLinkedEntities); final UserDTOPreProcessor userDTODecorator = getDefaultUserProcessor(includeLinkedEntities);
sendDefaultUserRequest(parameters,HttpRequestSender.REQUEST_TYPE.GET,userDTODecorator,new UrlProcessor(){ sendDefaultUserRequest(parameters, ApiClient.REQUEST_TYPE.GET, userDTODecorator, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/person/"+externalIdentifier); return (url + "/person/" + externalIdentifier);
} }
}); });
} }
@Override @Override
@Transactional @Transactional
public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) throws ExternalImportException{ public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) throws ExternalImportException {
final Map<String,String> parameters = new HashMap<String,String>(); final Map<String, String> parameters = new HashMap<String, String>();
final UserDTOPreProcessor employeeDTODecorator = getDefaultEmployeeUserProcessor(includeLinkedEntities);//Force all returned users to be assigned the local "Supervisor" role final UserDTOPreProcessor employeeDTODecorator = getDefaultEmployeeUserProcessor(includeLinkedEntities);//Force all returned users to be assigned the local "Supervisor" role
if(!role.equals(Roles.EMPLOYEE)) //Only supports employees currently if (!role.equals(Roles.EMPLOYEE)) //Only supports employees currently
{
throw new UnsupportedOperationException("Sorry, only the EMPLOYEE role is currently supported"); throw new UnsupportedOperationException("Sorry, only the EMPLOYEE role is currently supported");
sendDefaultUserRequest(parameters,HttpRequestSender.REQUEST_TYPE.GET, employeeDTODecorator,new UrlProcessor(){ }
sendDefaultUserRequest(parameters, ApiClient.REQUEST_TYPE.GET, employeeDTODecorator, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/orgunit/4/supervisors");//Hehe return (url + "/orgunit/4/supervisors");//Hehe
} }
}); });
} }
@Override @Override
public void importProjects(final String title) throws ExternalImportException { public void importProjects(final String title) throws ExternalImportException {
final Map<String,String> parameters = new HashMap<String,String>(); final Map<String, String> parameters = new HashMap<String, String>();
parameters.put("title", title); parameters.put("title", title);
Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(parameters,HttpRequestSender.REQUEST_TYPE.GET,null, new UrlProcessor(){ Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(parameters, ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/thesis"); return (url + "/thesis");
} }
}); });
final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(externalProjectSet); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(externalProjectSet);
for(ProjectDTO projectDTO : projectsWithParticipants){ for (ProjectDTO projectDTO : projectsWithParticipants) {
final Project project = projectDao.getProjectByIdentifier(projectDTO.id); final Project project = projectDao.getProjectByIdentifier(projectDTO.id);
if(project == null) if (project == null) {
logger.info("Importing new project: '" + projectDTO+"'"); logger.info("Importing new project: '" + projectDTO + "'");
else }
logger.info("Updating existing project: '" + projectDTO+"'"); else {
logger.info("Updating existing project: '" + projectDTO + "'");
}
importerFacade.mergeProject(project, projectDTO); importerFacade.mergeProject(project, projectDTO);
} }
} }
@Override @Override
public void importProject(final long externalIdentifier) throws ExternalImportException { public void importProject(final long externalIdentifier) throws ExternalImportException {
Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(new HashMap<String,String>(),HttpRequestSender.REQUEST_TYPE.GET,null, new UrlProcessor(){ Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/thesis/"+externalIdentifier); return (url + "/thesis/" + externalIdentifier);
} }
}); });
final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(externalProjectSet); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(externalProjectSet);
for(ProjectDTO projectDTO : projectsWithParticipants){ for (ProjectDTO projectDTO : projectsWithParticipants) {
final Project project = projectDao.getProjectByIdentifier(projectDTO.id); final Project project = projectDao.getProjectByIdentifier(projectDTO.id);
if(project == null) if (project == null) {
logger.info("Importing new project: '" + projectDTO+"'"); logger.info("Importing new project: '" + projectDTO + "'");
else }
logger.info("Updating existing project: '" + projectDTO+"'"); else {
logger.info("Updating existing project: '" + projectDTO + "'");
}
importerFacade.mergeProject(project, projectDTO); importerFacade.mergeProject(project, projectDTO);
} }
} }
@Override @Override
@Transactional @Transactional
public void importSupervisorUnits() throws ExternalImportException { public void importSupervisorUnits() throws ExternalImportException {
Set<UnitDTO> unitSet = fetchRemoteUnits(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor() { Set<UnitDTO> unitSet = fetchRemoteUnits(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/orgunit/4/subunits"); return (url + "/orgunit/4/subunits");
} }
}); });
importerFacade.addUnexistingUnitsAsKeywords(unitSet); importerFacade.addUnexistingUnitsAsKeywords(unitSet);
Set<PersonDTO> allSupervisorsOnUnits = new HashSet<PersonDTO>(); Set<PersonDTO> allSupervisorsOnUnits = new HashSet<PersonDTO>();
for (final UnitDTO unitDTO : unitSet){ for (final UnitDTO unitDTO : unitSet) {
Set<PersonDTO> supervisorSet = fetchSupervisorsOnUnit(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor() { Set<PersonDTO> supervisorSet = fetchSupervisorsOnUnit(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/orgunit/"+unitDTO.id+"/supervisors"); return (url + "/orgunit/" + unitDTO.id + "/supervisors");
} }
}); });
allSupervisorsOnUnits.addAll(supervisorSet); allSupervisorsOnUnits.addAll(supervisorSet);
if(!supervisorSet.isEmpty()){ if (!supervisorSet.isEmpty()) {
for (PersonDTO supervisorDTO : supervisorSet) { for (PersonDTO supervisorDTO : supervisorSet) {
importerFacade.addUnitToSupervisor(supervisorDTO, unitDTO); importerFacade.addUnitToSupervisor(supervisorDTO, unitDTO);
} }
} else }
logger.info("Unit: " + unitDTO.name + " has no supervisors attached."); else {
logger.info("Unit: " + unitDTO.name + " has no supervisors attached.");
}
} }
// Compare the list of supervisors with remote units with the list of // Compare the list of supervisors with remote units with the list of
// all supervisors in scipro, to make sure to remove units from the // all supervisors in scipro, to make sure to remove units from the
// users that doesn't have one in daisy. // users that doesn't have one in daisy.
logger.debug("Number of supervisors on remote units: " + allSupervisorsOnUnits.size()); logger.debug("Number of supervisors on remote units: " + allSupervisorsOnUnits.size());
importerFacade.removeUnitFromSupervisorsNotInSet(allSupervisorsOnUnits); importerFacade.removeUnitFromSupervisorsNotInSet(allSupervisorsOnUnits);
} }
@Override @Override
@Transactional @Transactional
public void importResearchAreas() throws ExternalImportException { public void importResearchAreas() throws ExternalImportException {
Set<ResearchAreaDTO> areaSet = fetchResearchAreas(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor() { Set<ResearchAreaDTO> areaSet = fetchResearchAreas(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(final String url){ String process(final String url) {
return (url+"/orgunit/4/researchAreas"); return (url + "/orgunit/4/researchAreas");
} }
}); });
logger.info("Received " + areaSet.size() + " research areas from remote and adding those who not exist to database"); logger.info("Received " + areaSet.size() + " research areas from remote and adding those who not exist to database");
if(!areaSet.isEmpty()){ if (!areaSet.isEmpty()) {
importerFacade.addUnexistingResearchAreas(areaSet); importerFacade.addUnexistingResearchAreas(areaSet);
} }
} }
private Set<PersonDTO> fetchSupervisorsOnUnit(final Map<String, String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, UrlProcessor urlProcessor) { private Set<PersonDTO> fetchSupervisorsOnUnit(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final Set<PersonDTO> dtoCache = new HashSet<PersonDTO>(); final Set<PersonDTO> dtoCache = new HashSet<PersonDTO>();
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler() { try {
client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
@Override
public void handleResponse(String response) { @Override
logger.info("Response received (from: "+ requestUrl+"): " + response); public void handleResponse(String response) {
final PersonDTOCollectionWrapper supervisorCollection = asSupervisorCollection(response); logger.info("Response received (from: " + requestUrl + "): " + response);
if(supervisorCollection.size() == 0){ final PersonDTOCollectionWrapper supervisorCollection = asSupervisorCollection(response);
throw new ExternalImportException("No supervisors found in remote"); if (supervisorCollection.size() == 0) {
} else { throw new ExternalImportException("No supervisors found in remote");
dtoCache.addAll(supervisorCollection.getPersons()); }
else {
dtoCache.addAll(supervisorCollection.getPersons());
}
logger.info("Received " + supervisorCollection.size() + " supervisor" + (supervisorCollection.size() == 1 ? "" : "s") + " from remote");
} }
logger.info("Received " + supervisorCollection.size() + " supervisor"+(supervisorCollection.size()==1?"":"s")+" from remote"); }, parameters, requestType);
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); catch (final ExternalImportException eie) {
try{
process(senderProxy);
} catch (final ExternalImportException eie){
logger.warn("No supervisors found"); logger.warn("No supervisors found");
} }
return dtoCache; return dtoCache;
} }
private Set<UnitDTO> fetchRemoteUnits(final Map<String,String> parameters,final HttpRequestSender.REQUEST_TYPE requestType, private Set<UnitDTO> fetchRemoteUnits(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType,
UrlProcessor urlProcessor) { UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final Set<UnitDTO> dtoCache = new HashSet<UnitDTO>(); final Set<UnitDTO> dtoCache = new HashSet<UnitDTO>();
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ try {
@Override client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
public void handleResponse(String response) { @Override
logger.info("Response received (from: "+requestUrl+"): " + response); public void handleResponse(String response) {
final UnitDTOCollectionWrapper unitCollection = asUnitCollection(response);//The query will always returns a collection, regardless of backing data logger.info("Response received (from: " + requestUrl + "): " + response);
if(unitCollection.size() == 0){//If at this point we have nothing, we have to throw. final UnitDTOCollectionWrapper unitCollection = asUnitCollection(response);//The query will always returns a collection, regardless of backing data
throw new ExternalImportException("No units found in remote"); if (unitCollection.size() == 0) {//If at this point we have nothing, we have to throw.
}else{ throw new ExternalImportException("No units found in remote");
dtoCache.addAll(unitCollection.getUnits()); }
else {
dtoCache.addAll(unitCollection.getUnits());
}
logger.info("Received " + unitCollection.size() + " unit" + (unitCollection.size() == 1 ? "" : "s") + " from remote");
} }
logger.info("Received " + unitCollection.size() + " unit"+(unitCollection.size()==1?"":"s")+" from remote"); }, parameters, requestType);
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); catch (final ExternalImportException eie) {
try{
process(senderProxy);
}catch(final ExternalImportException eie){
logger.warn("No units found"); logger.warn("No units found");
} }
return dtoCache; return dtoCache;
} }
@Override @Override
public boolean supportsRemoteOperations() { public boolean supportsRemoteOperations() {
return true; return true;
} }
/** /**
* Private utility method, sends request and signals failure via exceptions. * Private utility method, sends request and signals failure via exceptions.
*
* @param parameters * @param parameters
* @param requestType * @param requestType
*/ */
private void sendDefaultUserRequest(final Map<String,String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UserDTOPreProcessor preProcessor, final UrlProcessor urlProcessor){ private void sendDefaultUserRequest(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UserDTOPreProcessor preProcessor, final UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
@Override @Override
public void handleResponse(String response) { public void handleResponse(String response) {
logger.info("Response recieved (from: "+requestUrl+"): " + response); logger.info("Response recieved (from: " + requestUrl + "): " + response);
final UserDTOCollectionWrapper userCollection = asUserCollectionWrapper(response);//The query will always returns a collection, regardless of backing data final UserDTOCollectionWrapper userCollection = asUserCollectionWrapper(response);//The query will always returns a collection, regardless of backing data
if(userCollection.size() == 0){//If at this point we have nothing, we have to throw. if (userCollection.size() == 0) {//If at this point we have nothing, we have to throw.
throw new ExternalImportException("No users found in remote"); throw new ExternalImportException("No users found in remote");
}else{ }
for(final UserDTO userDTO:userCollection){ else {
for (final UserDTO userDTO : userCollection) {
final User user = userDao.getUserByIdentifier(userDTO.id); final User user = userDao.getUserByIdentifier(userDTO.id);
if(user == null) if (user == null) {
logger.info("Importing new user: '" + userDTO+"'"); logger.info("Importing new user: '" + userDTO + "'");
else }
logger.info("Updating existing user: '" + userDTO+"'"); else {
importerFacade.mergeUser(user, (preProcessor!=null?preProcessor.process(userDTO):userDTO)); logger.info("Updating existing user: '" + userDTO + "'");
}
importerFacade.mergeUser(user, (preProcessor != null ? preProcessor.process(userDTO) : userDTO));
} }
} }
logger.info("Recieved " + userCollection.size() + " user"+(userCollection.size()==1?"":"s")+" from remote"); logger.info("Recieved " + userCollection.size() + " user" + (userCollection.size() == 1 ? "" : "s") + " from remote");
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); }, parameters, requestType);
process(senderProxy);
} }
private Set<ProjectDTO> fetchRemoteProjects(final Map<String,String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final ProjectDTOPreProcessor preProcessor, final UrlProcessor urlProcessor){
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); private Set<ProjectDTO> fetchRemoteProjects(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final Set<ProjectDTO> dtoCache = new HashSet<ProjectDTO>(); final Set<ProjectDTO> dtoCache = new HashSet<ProjectDTO>();
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ try {
@Override client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
public void handleResponse(String response) { @Override
logger.info("Response recieved (from: "+requestUrl+"): " + response); public void handleResponse(String response) {
final ProjectDTOCollectionWrapper projectCollection = asProjectCollection(response);//The query will always returns a collection, regardless of backing data logger.info("Response recieved (from: " + requestUrl + "): " + response);
if(projectCollection.size() == 0){//If at this point we have nothing, we have to throw. final ProjectDTOCollectionWrapper projectCollection = asProjectCollection(response);//The query will always returns a collection, regardless of backing data
throw new ExternalImportException("No projects found in remote"); if (projectCollection.size() == 0) {//If at this point we have nothing, we have to throw.
}else{ throw new ExternalImportException("No projects found in remote");
dtoCache.addAll(projectCollection.getProjects()); }
else {
dtoCache.addAll(projectCollection.getProjects());
}
logger.info("Recieved " + projectCollection.size() + " project" + (projectCollection.size() == 1 ? "" : "s") + " from remote");
} }
logger.info("Recieved " + projectCollection.size() + " project"+(projectCollection.size()==1?"":"s")+" from remote"); }, parameters, requestType);
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); catch (final ExternalImportException eie) {
try{
process(senderProxy);
}catch(final ExternalImportException eie){
logger.warn("No projects found, this may or may not indicate a problem"); logger.warn("No projects found, this may or may not indicate a problem");
} }
return dtoCache; return dtoCache;
} }
private Set<UsernameDTO> fetchRemoteUsernames(final Map<String,String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { private Set<UsernameDTO> fetchRemoteUsernames(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final Set<UsernameDTO> dtoCache = new HashSet<UsernameDTO>(); final Set<UsernameDTO> dtoCache = new HashSet<UsernameDTO>();
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler() { try {
client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
@Override
public void handleResponse(String response) { @Override
logger.info("Response recieved (from: "+requestUrl+"): " + response); public void handleResponse(String response) {
final UsernameDTOCollectionWrapper usernameCollection = asUsernameCollection(response); logger.info("Response recieved (from: " + requestUrl + "): " + response);
if(usernameCollection.size() == 0){ final UsernameDTOCollectionWrapper usernameCollection = asUsernameCollection(response);
throw new ExternalImportException("No usernames found in remote"); if (usernameCollection.size() == 0) {
}else{ throw new ExternalImportException("No usernames found in remote");
dtoCache.addAll(usernameCollection.getUsernames()); }
else {
dtoCache.addAll(usernameCollection.getUsernames());
}
logger.info("Received " + usernameCollection.size() + " usernames" + (usernameCollection.size() == 1 ? "" : "s") + " from remote");
} }
logger.info("Received " + usernameCollection.size() + " usernames"+(usernameCollection.size()==1?"":"s")+" from remote"); }, parameters, requestType);
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); catch (final ExternalImportException eie) {
try{
process(senderProxy);
} catch (final ExternalImportException eie){
logger.warn("No usernames found"); logger.warn("No usernames found");
} }
return dtoCache; return dtoCache;
} }
private Set<ResearchAreaDTO> fetchResearchAreas(final Map<String, String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { private Set<ResearchAreaDTO> fetchResearchAreas(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final Set<ResearchAreaDTO> dtoCache = new HashSet<ResearchAreaDTO>(); final Set<ResearchAreaDTO> dtoCache = new HashSet<ResearchAreaDTO>();
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ try {
@Override client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
public void handleResponse(String response) { @Override
logger.info("Response recieved (from: "+requestUrl+"): " + response); public void handleResponse(String response) {
final ResearchAreaDTOCollectionWrapper areaCollection = asAreaCollection(response);//The query will always returns a collection, regardless of backing data logger.info("Response recieved (from: " + requestUrl + "): " + response);
if(areaCollection.size() == 0){//If at this point we have nothing, we have to throw. final ResearchAreaDTOCollectionWrapper areaCollection = asAreaCollection(response);//The query will always returns a collection, regardless of backing data
throw new ExternalImportException("No research areas found in remote"); if (areaCollection.size() == 0) {//If at this point we have nothing, we have to throw.
}else{ throw new ExternalImportException("No research areas found in remote");
dtoCache.addAll(areaCollection.getAreas()); }
else {
dtoCache.addAll(areaCollection.getAreas());
}
logger.info("Recieved " + areaCollection.size() + " research area" + (areaCollection.size() == 1 ? "" : "s") + " from remote");
} }
logger.info("Recieved " + areaCollection.size() + " research area"+(areaCollection.size()==1?"":"s")+" from remote"); }, parameters, requestType);
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); catch (final ExternalImportException eie) {
try{
process(senderProxy);
}catch(final ExternalImportException eie){
logger.warn("No research areas found, this may or may not indicate a problem"); logger.warn("No research areas found, this may or may not indicate a problem");
} }
return dtoCache; return dtoCache;
} }
private Set<ProjectParticipantDTO> fetchParticipants(final Map<String, String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { private Set<ProjectParticipantDTO> fetchParticipants(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) {
final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl()));
final Set<ProjectParticipantDTO> dtoCache = new HashSet<ProjectParticipantDTO>(); final Set<ProjectParticipantDTO> dtoCache = new HashSet<ProjectParticipantDTO>();
final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ try {
@Override client.processRequest(requestUrl, new AbstractDtoResponseHandler() {
public void handleResponse(String response) { @Override
logger.info("Response recieved (from: "+requestUrl+"): " + response); public void handleResponse(String response) {
final ProjectParticipantDTOCollectionWrapper participantCollection = asParticipantCollection(response);//The query will always returns a collection, regardless of backing data logger.info("Response recieved (from: " + requestUrl + "): " + response);
if(participantCollection.size() == 0){//If at this point we have nothing, we have to throw. final ProjectParticipantDTOCollectionWrapper participantCollection = asParticipantCollection(response);//The query will always returns a collection, regardless of backing data
throw new ExternalImportException("No project participants found in remote"); if (participantCollection.size() == 0) {//If at this point we have nothing, we have to throw.
}else{ throw new ExternalImportException("No project participants found in remote");
dtoCache.addAll(participantCollection.getParticipants()); }
else {
dtoCache.addAll(participantCollection.getParticipants());
}
logger.info("Recieved " + participantCollection.size() + " project participant" + (participantCollection.size() == 1 ? "" : "s") + " from remote");
} }
logger.info("Recieved " + participantCollection.size() + " project participant"+(participantCollection.size()==1?"":"s")+" from remote"); }, parameters, requestType);
} }
}, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); catch (final ExternalImportException eie) {
try{
process(senderProxy);
}catch(final ExternalImportException eie){
logger.warn("No project participants found, this may or may not indicate a problem"); logger.warn("No project participants found, this may or may not indicate a problem");
} }
return dtoCache; return dtoCache;
} }
private String getRequestUrl(){ /**
return applicationSettings.getRemoteLookupUrl(); * @return
} * @deprecated Should be removed. This is set in the client config in applicationContext.xml
private String getRequestUser() { */
return applicationSettings.getRemoteLookupUser(); private String getRequestUrl() {
} return "";
private String getRequestPassword() {
return applicationSettings.getRemoteLookupPassword();
}
private void process(final HttpRequestSender proxy) throws ExternalImportException{
try{
proxy.processRequest();
}catch(final IOException ioe){
logger.error("A fatal IO exception has occured while contacting remote host at: " + getRequestUrl());
throw new ExternalImportException(ioe);
}catch(final HttpRemoteRespondedWithFailureException hrrwfe){
logger.error("Remote host: " + getRequestUrl() + " responded with failure: "+ hrrwfe.getMessage());
throw new ExternalImportException(hrrwfe);//Use getCause etc to find out the response code and act on it in some meaningful way
}
} }
private UserDTOPreProcessor getDefaultUserProcessor(boolean includeLinkedEntities) { private UserDTOPreProcessor getDefaultUserProcessor(boolean includeLinkedEntities) {
if(!includeLinkedEntities) if (!includeLinkedEntities) {
return new UserDTOPreProcessor(); return new UserDTOPreProcessor();
return new UserDTOPreProcessor(){ }
return new UserDTOPreProcessor() {
@Override @Override
UserDTO process(final UserDTO userDTO){ UserDTO process(final UserDTO userDTO) {
final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, null, new UrlProcessor(){ final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return (url+"/person/"+userDTO.id+"/theses"); return (url + "/person/" + userDTO.id + "/theses");
} }
}); });
//Fetch authors and supervisors for each project //Fetch authors and supervisors for each project
final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(fetchedProjects); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(fetchedProjects);
final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return(url+"/person/"+userDTO.id+"/usernames"); return (url + "/person/" + userDTO.id + "/usernames");
} }
}); });
userDTO.projects = projectsWithParticipants; userDTO.projects = projectsWithParticipants;
@ -410,88 +419,85 @@ public class ExternalImporterDaisyImpl implements ExternalImporter {
} }
}; };
} }
private UserDTOPreProcessor getDefaultEmployeeUserProcessor(final boolean includeLinkedEntities) { private UserDTOPreProcessor getDefaultEmployeeUserProcessor(final boolean includeLinkedEntities) {
return new UserDTOPreProcessor(){ return new UserDTOPreProcessor() {
@Override @Override
UserDTO process(final UserDTO userDTO){ UserDTO process(final UserDTO userDTO) {
if(includeLinkedEntities){ if (includeLinkedEntities) {
final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, null, new UrlProcessor(){ final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return (url+"/person/"+userDTO.id+"/theses"); return (url + "/person/" + userDTO.id + "/theses");
} }
}); });
final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(fetchedProjects); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(fetchedProjects);
userDTO.projects = projectsWithParticipants; userDTO.projects = projectsWithParticipants;
} }
final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return(url+"/person/"+userDTO.id+"/usernames"); return (url + "/person/" + userDTO.id + "/usernames");
} }
}); });
userDTO.usernames = fetchedUsernames; userDTO.usernames = fetchedUsernames;
final Set<ResearchAreaDTO> fetchedResearchAreas = fetchResearchAreas(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ final Set<ResearchAreaDTO> fetchedResearchAreas = fetchResearchAreas(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return (url+"/person/"+userDTO.id+"/researchAreas"); return (url + "/person/" + userDTO.id + "/researchAreas");
} }
}); });
userDTO.researchAreas = fetchedResearchAreas; userDTO.researchAreas = fetchedResearchAreas;
//Force employee role data to be on the DTO //Force employee role data to be on the DTO
UserRoleDTO employeeRole = new UserRoleDTO(); UserRoleDTO employeeRole = new UserRoleDTO();
employeeRole.role = UserRoleDTO.EXTERNAL_USER_ROLES.SUPERVISOR_ROLE.asExternal(); employeeRole.role = UserRoleDTO.EXTERNAL_USER_ROLES.SUPERVISOR_ROLE.asExternal();
if(!userDTO.roles.contains(employeeRole)){ if (!userDTO.roles.contains(employeeRole)) {
userDTO.roles.add(employeeRole); userDTO.roles.add(employeeRole);
} }
return userDTO; return userDTO;
} }
}; };
} }
private Set<ProjectDTO> projectDTOWithParticipants(Set<ProjectDTO> fetchedProjects){ private Set<ProjectDTO> projectDTOWithParticipants(Set<ProjectDTO> fetchedProjects) {
Set<ProjectDTO> projects = new HashSet<ProjectDTO>(fetchedProjects); Set<ProjectDTO> projects = new HashSet<ProjectDTO>(fetchedProjects);
for (final ProjectDTO projectDTO : projects) { for (final ProjectDTO projectDTO : projects) {
Set<ProjectParticipantDTO> combinedSet = new HashSet<ProjectParticipantDTO>(); Set<ProjectParticipantDTO> combinedSet = new HashSet<ProjectParticipantDTO>();
final Set<ProjectParticipantDTO> fetchedAuthors = fetchParticipants(new HashMap<String, String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ final Set<ProjectParticipantDTO> fetchedAuthors = fetchParticipants(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return(url+"/thesis/"+projectDTO.id+"/student"); return (url + "/thesis/" + projectDTO.id + "/student");
} }
}); });
combinedSet.addAll(fetchedAuthors); combinedSet.addAll(fetchedAuthors);
final Set<ProjectParticipantDTO> fetchedOtherParticipants = fetchParticipants(new HashMap<String, String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ final Set<ProjectParticipantDTO> fetchedOtherParticipants = fetchParticipants(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() {
@Override @Override
String process(String url){ String process(String url) {
return(url+"/thesis/"+projectDTO.id+"/contributor"); return (url + "/thesis/" + projectDTO.id + "/contributor");
} }
}); });
combinedSet.addAll(fetchedOtherParticipants); combinedSet.addAll(fetchedOtherParticipants);
projectDTO.participants = combinedSet; projectDTO.participants = combinedSet;
} }
return projects; return projects;
} }
/** /**
* Small utility interface/default implementation used to preprocess DTO objects, intended for anonymous inner class-usage. * Small utility interface/default implementation used to preprocess DTO objects, intended for anonymous inner class-usage.
*/ */
private class UserDTOPreProcessor{ private class UserDTOPreProcessor {
UserDTO process(UserDTO userDTO){ UserDTO process(UserDTO userDTO) {
return userDTO; return userDTO;
} }
} }
private class ProjectDTOPreProcessor{
ProjectDTO process(ProjectDTO projectDTO){ private class UrlProcessor {
return projectDTO; String process(String url) {
}
}
private class UrlProcessor{
String process(String url){
return url; return url;
} }
} }
} }

@ -1,7 +1,6 @@
package se.su.dsv.scipro.io.impl; package se.su.dsv.scipro.io.impl;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import se.su.dsv.scipro.io.ExternalImporter; import se.su.dsv.scipro.io.ExternalImporter;
import se.su.dsv.scipro.io.exceptions.ExternalImportException; import se.su.dsv.scipro.io.exceptions.ExternalImportException;
import se.su.dsv.scipro.security.auth.roles.Roles; import se.su.dsv.scipro.security.auth.roles.Roles;
@ -12,38 +11,51 @@ import se.su.dsv.scipro.security.auth.roles.Roles;
*/ */
public class ExternalImporterDefaultImpl implements ExternalImporter { public class ExternalImporterDefaultImpl implements ExternalImporter {
private final Logger logger = Logger.getLogger(ExternalImporterDefaultImpl.class); private final Logger logger = Logger.getLogger(ExternalImporterDefaultImpl.class);
@Override
public String getLookupUrl() {
return "<not specified>";
}
@Override @Override
public void importUser(final String userName, boolean includeLinkedEntities) { public void importUser(final String userName, boolean includeLinkedEntities) {
logger.debug("Dummy implementation, the user: "+userName+" will not be imported"); logger.debug("Dummy implementation, the user: " + userName + " will not be imported");
} }
@Override @Override
public void importUser(final long externalIdentifier, boolean includeLinkedEntities) { public void importUser(final long externalIdentifier, boolean includeLinkedEntities) {
logger.debug("Dummy implementation, the user with identifier: "+externalIdentifier+" will not be imported"); logger.debug("Dummy implementation, the user with identifier: " + externalIdentifier + " will not be imported");
} }
@Override @Override
public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) { public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) {
logger.debug("Dummy implementation, no users of role: " + role + " will be imported"); logger.debug("Dummy implementation, no users of role: " + role + " will be imported");
} }
@Override @Override
public void importProject(long externalIdentifier){ public void importProject(long externalIdentifier) {
logger.debug("Dummy implementation, no project with the id: " + externalIdentifier + " will be imported"); logger.debug("Dummy implementation, no project with the id: " + externalIdentifier + " will be imported");
} }
@Override @Override
public void importProjects(String title) throws ExternalImportException { public void importProjects(String title) throws ExternalImportException {
logger.debug("Dummy implementation, no project matching the title: " + title + " will be imported"); logger.debug("Dummy implementation, no project matching the title: " + title + " will be imported");
} }
@Override @Override
public boolean supportsRemoteOperations() { public boolean supportsRemoteOperations() {
return false; return false;
} }
@Override @Override
public void importSupervisorUnits() throws ExternalImportException { public void importSupervisorUnits() throws ExternalImportException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override @Override
public void importResearchAreas() throws ExternalImportException { public void importResearchAreas() throws ExternalImportException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
} }

@ -12,7 +12,7 @@
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
default-autowire="byType"> default-autowire="byType">
<jpa:repositories base-package="se.su.dsv.scipro.springdata" /> <jpa:repositories base-package="se.su.dsv.scipro.springdata"/>
<!-- Sets up spring autowire configuration based on annotations --> <!-- Sets up spring autowire configuration based on annotations -->
<context:annotation-config/> <context:annotation-config/>
@ -63,13 +63,19 @@
<!-- Load data initializer for default table-data --> <!-- Load data initializer for default table-data -->
<bean class="se.su.dsv.scipro.DataInitialiser" init-method="dataInit"/> <bean class="se.su.dsv.scipro.DataInitialiser" init-method="dataInit"/>
<!-- Importer used for remote importing work, use "ExternalImporterDefaultImpl" if you have no remote-import implementation capable of satisfying "ExternalImporter" interface. --> <!-- Importer used for remote importing work, use "ExternalImporterDefaultImpl" if you have no remote-import implementation capable of satisfying "ExternalImporter" interface. -->
<bean id="externalImporter" class="se.su.dsv.scipro.io.impl.ExternalImporterDaisyImpl"/> <bean id="externalImporter" class="se.su.dsv.scipro.io.impl.ExternalImporterDaisyImpl">
<property name="client" ref="dsvApiClient"/>
</bean>
<bean id="dsvApiClient" class="se.su.dsv.scipro.io.http.ApiClient">
<!-- This property points to the location of the remote system used for json requests -->
<property name="baseUrl" value="${remote.lookup.url}"/>
<property name="user" value="thesis"/>
<property name="password" value="dqyhIM8LU5LQ53T3aJNz4SVXeTQ95dLGkN7JlLOv7X7jeTR2NR"/>
</bean>
<!-- Defines global settings for the application --> <!-- Defines global settings for the application -->
<bean id="applicationSettings" class="se.su.dsv.scipro.ApplicationSettings"> <bean id="applicationSettings" class="se.su.dsv.scipro.ApplicationSettings">
<property name="remoteLookupUrl" value="https://api.dsv.su.se/rest"/>
<property name="remoteLookupUser" value="thesis"/>
<property name="remoteLookupPassword" value="dqyhIM8LU5LQ53T3aJNz4SVXeTQ95dLGkN7JlLOv7X7jeTR2NR"/>
<!-- This property points to the location of the remote system used for json requests -->
<!-- External auth support (via J2EE standard mechanism REMOTE_USER), if true: other authentication mechanics will be bypassed.--> <!-- External auth support (via J2EE standard mechanism REMOTE_USER), if true: other authentication mechanics will be bypassed.-->
<property name="acceptExternalAuthentication" value="true"/> <property name="acceptExternalAuthentication" value="true"/>
</bean> </bean>