Wicket serialization issue with WebApplication - serialization

I'm continuing on with a logging behavior using the WebSocketBehavior. It currently logs the correct data to a console, but also throws a terrible serialization error. It is because I am providing the WicketApplication itself as a constructor argument for the behavior. I've tried passing it my session object and using that to get the WebApplication, but it consistently returns null. The broadcaster object requires the application in order to function properly. My question is how can I provide the WebApplication to the behavior while avoiding the nasty serialization error?? Here is my behavior class:
public class LogWebSocketBehavior extends WebSocketBehavior implements Serializable {
private static final long serialVersionUID = 1L;
private Console console;
private Handler logHandler;
private Model<LogRecord> model = new Model<>();
private WebApplication application;
public LogWebSocketBehavior(Console console, WebApplication application) {
super();
configureLogger();
this.console = console;
this.application = application;
}
private void configureLogger() {
Enumeration<String> list = LogManager.getLogManager().getLoggerNames();
list.hasMoreElements();
Logger l = Logger.getLogger(AppUtils.loggerName);
l.addHandler(getLoggerHandler());
}
#Override
protected synchronized void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) {
LogRecord r = model.getObject();
sendRecordToConsole(handler, r);
}
private Handler getLoggerHandler() {
return new LogHandler() {
private static final long serialVersionUID = 1L;
#Override
public void publish(LogRecord record) {
model.setObject(record);
sendToAllConnectedClients("data");
}
};
}
private synchronized void sendToAllConnectedClients(String message) {
IWebSocketConnectionRegistry registry = new SimpleWebSocketConnectionRegistry();
WebSocketPushBroadcaster b = new WebSocketPushBroadcaster(registry);
b.broadcastAll(application, new Message());
}
private void sendRecordToConsole(WebSocketRequestHandler handler, LogRecord r) {
Level level = r.getLevel();
if (level.equals(Level.INFO)) {
console.info(handler, new SimpleFormatter().formatMessage(r));
} else {
console.error(handler, new SimpleFormatter().formatMessage(r));
}
}
class Message implements IWebSocketPushMessage {
public Message() {
}
}
}
Here is the panel that is being used to display the messages:
public class FooterPanel extends Panel {
private static final long serialVersionUID = 1L;
private Form form;
private Console console;
public FooterPanel(String id) {
super(id);
}
#Override
public void onInitialize() {
super.onInitialize();
form = new Form("form");
form.add(console = getConsole("feedback_console"));
console.setOutputMarkupId(true);
form.setOutputMarkupId(true);
add(form);
add(getLoggingBehavior());
}
private Console getConsole(String id) {
return new Console(id) {
private static final long serialVersionUID = 1L;
};
}
private WebSocketBehavior getLoggingBehavior() {
return new LogWebSocketBehavior(console, this.getWebApplication());
}
}
I updated my behavior as follows:
public class LogWebSocketBehavior extends WebSocketBehavior implements Serializable {
private static final long serialVersionUID = 1L;
private Console console;
private Handler logHandler;
private Model<LogRecord> model = new Model<>();
public LogWebSocketBehavior(Console console) {
super();
configureLogger();
this.console = console;
}
private void configureLogger() {
Enumeration<String> list = LogManager.getLogManager().getLoggerNames();
list.hasMoreElements();
Logger l = Logger.getLogger(AppUtils.loggerName);
l.addHandler(getLoggerHandler());
}
#Override
protected synchronized void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) {
LogRecord r = model.getObject();
sendRecordToConsole(handler, r);
}
private Handler getLoggerHandler() {
return new LogHandler() {
private static final long serialVersionUID = 1L;
#Override
public void publish(LogRecord record) {
model.setObject(record);
sendToAllConnectedClients("data");
}
};
}
private synchronized void sendToAllConnectedClients(String message) {
WebApplication application = WebApplication.get();
IWebSocketConnectionRegistry registry = new SimpleWebSocketConnectionRegistry();
WebSocketPushBroadcaster b = new WebSocketPushBroadcaster(registry);
b.broadcastAll(application, new Message());
}
private void sendRecordToConsole(WebSocketRequestHandler handler, LogRecord r) {
Level level = r.getLevel();
String message = AppUtils.consoleDateTimeFormat.format(LocalDateTime.now()) + " - " + AppUtils.LogFormatter.formatMessage(r);
if (level.equals(Level.INFO)) {
console.info(handler, message);
} else {
console.error(handler, message);
}
}
class Message implements IWebSocketPushMessage {
public Message() {
}
}
}
And I'm back to the original issues I started with, which is the following error:
ERROR - ErrorLogger - Job (report.DB5E002E046235586592E7E984338DEE3 : 653 threw an exception.
org.quartz.SchedulerException:
Job threw an unhandled exception. [See nested exception: org.apache.wicket.WicketRuntimeException: There is no application attached to current thread DefaultQuartzScheduler_Worker-1]
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: org.apache.wicket.WicketRuntimeException: There is no application attached to current thread DefaultQuartzScheduler_Worker-1
at org.apache.wicket.Application.get(Application.java:236)
at org.apache.wicket.protocol.http.WebApplication.get(WebApplication.java:160)
at eb.wicket.behaviors.LogWebSocketBehavior.sendToAllConnectedClients(LogWebSocketBehavior.java:77)
at eb.wicket.behaviors.LogWebSocketBehavior.access$100(LogWebSocketBehavior.java:29)
at eb.wicket.behaviors.LogWebSocketBehavior$1.publish(LogWebSocketBehavior.java:70)
Finally working as desired.. Here's the behavior class:
public class LogWebSocketBehavior extends WebSocketBehavior implements Serializable {
private static final long serialVersionUID = 1L;
private Console console;
private Model<LogRecord> model = new Model<>();
public LogWebSocketBehavior(Console console) {
super();
configureLogger();
this.console = console;
}
private void configureLogger() {
Enumeration<String> list = LogManager.getLogManager().getLoggerNames();
list.hasMoreElements();
Logger l = Logger.getLogger(AppUtils.loggerName);
l.addHandler(getLoggerHandler());
}
#Override
protected synchronized void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) {
LogRecord r = model.getObject();
sendRecordToConsole(handler, r);
}
private Handler getLoggerHandler() {
return new LogHandler() {
private static final long serialVersionUID = 1L;
#Override
public void publish(LogRecord record) {
model.setObject(record);
sendToAllConnectedClients("data");
}
};
}
private synchronized void sendToAllConnectedClients(String message) {
IWebSocketConnectionRegistry registry = new SimpleWebSocketConnectionRegistry();
WebSocketPushBroadcaster b = new WebSocketPushBroadcaster(registry);
b.broadcastAll(Application.get("eb.wicket.MyWicketFilter"), new Message());
}
private void sendRecordToConsole(WebSocketRequestHandler handler, LogRecord r) {
Level level = r.getLevel();
String message = AppUtils.consoleDateTimeFormat.format(LocalDateTime.now()) + " - " + AppUtils.LogFormatter.formatMessage(r);
if (level.equals(Level.INFO)) {
console.info(handler, message);
} else {
console.error(handler, message);
}
}
class Message implements IWebSocketPushMessage {
public Message() {
}
}
}

Instead of keeping a reference to the Application just look it up when needed: Application.get().
After updating your question we can see:
Caused by: org.apache.wicket.WicketRuntimeException:
There is no application attached to current thread DefaultQuartzScheduler_Worker-1
This explains it - this is a thread started by Quartz, it is not a http thread.
The only way to overcome this is to use Application.get(String). The value should be the application name (Application#getName()) that is specified as a value for <filter-name> in your web.xml.
This way you can get the Application instance, but there is no way to do the same for Session and/or RequestCycle in case you need them too.

Related

How to clean autowired object after each test execution

How to clean autowired object after each test execution. In my example TestClassSettings object does not get clean property and it uses the previous test class value. Here is the example:
TestClassSettings.java
#Component
public class TestClassSettings{
private String titleUnitCode = "99";
private String fte = "1";
private String testIndicator = "";
public String getTitleUnitCode() {
return titleUnitCode;
}
public void setTitleUnitCode(String titleUnitCode) {
this.titleUnitCode = titleUnitCode;
}
public String getFte() {
return fte;
}
public void setFte(String fte) {
this.fte = fte;
}
public String getTestIndicator() {
return testIndicator;
}
public void setTestIndicator(String testIndicator) {
this.testIndicator = testIndicator;
}
}
testClassSettings instance is not getting clean in between test cases.
TestLeaveHourCal_bweh6.java
#TestMethodOrder(OrderAnnotation.class)
#SpringJUnitWebConfig(locations = { "classpath:service.xml"})
#TestInstance(Lifecycle.PER_CLASS)
public class TestLeaveHourCal_bweh6 {
#Autowired
private ApproveTimesheetService approveTimesheetService;
#Autowired
private ComparePayUpdates comparePayUpdates;
#Autowired
public TestClassSettings testClassSettings; /* variable access type needs public */;
#Autowired
#RegisterExtension
protected CreateTimesheetBeforeTestExecutionCallback beforeTestExecutionCallback; /* can not be private */
#BeforeAll
public void setup() throws Exception {
/* START SETTINGS */
testClassSettings.setTestIndicator("6");
testClassSettings.setTitleUnitCode("99");
testClassSettings.setFte("0.5");
/* END SETTINGS */
}
#Test
#Order(1)
#Tag("setBaselinePayUpdates")
public void setBaselinePayUpdates() throws Exception {
}
Added #DirtiesContext(classMode = ClassMode.AFTER_CLASS) to fix the issue

infinispan 9.4 - Listeners and event filter

I'm trying to use Listeners with filters in a distributed cache with two instances of Infinispan 9.4.0 and Hot Rod Client. When I try to put a new entry in cache, I get the following exception:
[Server:instance-one] 13:09:57,468 ERROR [stderr] (HotRod-ServerHandler-4-2) Exception in thread "HotRod-ServerHandler-4-2" org.infinispan.commons.CacheException: ISPN000936: Class 'com.cm.broadcaster.infinispan.entity.EntityDemo' blocked by deserialization white list. Adjust the configuration serialization white list regular expression to include this class.
This is the cache configuration:
<distributed-cache name="entityCache" remote-timeout="3000" statistics-available="false">
<memory>
<object size="20" strategy="LRU" />
</memory>
<compatibility enabled="true"/>
<file-store path="entity-store" passivation="true"/>
<indexing index="NONE"/>
<state-transfer timeout="60000" chunk-size="1024"/>
</distributed-cache>
This is my demo class:
public class EntityDemo implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String name;
private String value;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
The EventFilterFactory:
#NamedFactory(name="entity-event-filter-factory")
public class EntityEventFilterFactory implements CacheEventFilterFactory {
#Override
public CacheEventFilter<String, EntityDemo> getFilter(Object[] params) {
return new EntityEventFilter(params);
}
}
The EventFilter:
public class EntityEventFilter implements Serializable, CacheEventFilter<String, EntityDemo> {
private static final long serialVersionUID = 1L;
private final long filter;
public EntityEventFilter(Object[] params) {
this.filter = Long.valueOf(String.valueOf(params[0]));
}
#Override
public boolean accept(String key, EntityDemo oldValue, Metadata oldMetadata, EntityDemo newValue, Metadata newMetadata, EventType eventType) {
if (eventType.isCreate()) {
if (oldValue.getId() % filter == 0)
return true;
}
return false;
}
}
My test code:
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.addServers("localhost:11222");
RemoteCacheManager rcm = new RemoteCacheManager(cb.build());
RemoteCache<String, EntityDemo> rc = rcm.<String,
EntityDemo>getCache("entityCache");
rc.addClientListener(new CustomListener(), new Object[]{"1"}, null);
EntityDemo e = new EntityDemo();
e.setId(1);
e.setName("Demo");
e.setValue("Demo");
rc.put("1", e);
The listener:
#ClientListener(filterFactoryName="entity-event-filter-factory")
public class CustomListener {
#ClientCacheEntryCreated
public void entryCreated(ClientCacheEntryCreatedEvent<String> event) {
System.out.println("Entry created!");
System.out.println(event.getKey());
}
}
I have looked about white list for serialization, but I have found nothing.
I tried changing object in memory configuration for binary and disabling compatibility, but then I get a new exception:
[Server:instance-one] 13:56:42,131 ERROR [org.infinispan.interceptors.impl.InvocationContextInterceptor] (HotRod-ServerHandler-4-2) ISPN000136: Error executing command PutKeyValueCommand, writing keys [WrappedByteArray{bytes=[B0x01012903033E0131, hashCode=1999574342}]: java.lang.ClassCastException: java.lang.String cannot be cast to com.cm.broadcaster.infinispan.entity.EntityDemo
Can anyone help me with this?
Have you tried this? Passing the -Dinfinispan.deserialization.whitelist.classes property to the server.
http://infinispan.org/docs/stable/upgrading/upgrading.html#deserialization_whitelist

Spring Cloud: testing S3 client with TestContainters

I use Spring Cloud's ResourceLoader to access S3, e.g.:
public class S3DownUpLoader {
private final ResourceLoader resourceLoader;
#Autowired
public S3DownUpLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public String storeOnS3(String filename, byte[] data) throws IOException {
String location = "s3://" + bucket + "/" + filename;
WritableResource writeableResource = (WritableResource) this.resourceLoader.getResource(location);
FileCopyUtils.copy( data, writeableResource.getOutputStream());
return filename;
}
It works okey and I need help to test the code with Localstack/Testcontainers. I've tried following test, but it does not work - my production profile gets picked up(s3 client with localstack config is not injected):
#RunWith(SpringRunner.class)
#SpringBootTest
public class S3DownUpLoaderTest {
#ClassRule
public static LocalStackContainer localstack = new LocalStackContainer().withServices(S3);
#Autowired
S3DownUpLoader s3DownUpLoader;
#Test
public void testA() {
s3DownUpLoader.storeOnS3(...);
}
#TestConfiguration
#EnableContextResourceLoader
public static class S3Configuration {
#Primary
#Bean(destroyMethod = "shutdown")
public AmazonS3 amazonS3() {
return AmazonS3ClientBuilder
.standard()
.withEndpointConfiguration(localstack.getEndpointConfiguration(S3))
.withCredentials(localstack.getDefaultCredentialsProvider())
.build();
}
}
}
as we discussed on GitHub,
We solve this problem in a slightly different way. I've actually never seen the way you use the WritableResource, which looks very interesting. None the less, this is how we solve this issue:
#RunWith(SpringRunner.class)
#SpringBootTest(properties = "spring.profiles.active=test")
#ContextConfiguration(classes = AbstractAmazonS3Test.S3Configuration.class)
public abstract class AbstractAmazonS3Test {
private static final String REGION = Regions.EU_WEST_1.getName();
/**
* Configure S3.
*/
#TestConfiguration
public static class S3Configuration {
#Bean
public AmazonS3 amazonS3() {
//localstack docker image is running locally on port 4572 for S3
final String serviceEndpoint = String.format("http://%s:%s", "127.0.0.1", "4572");
return AmazonS3Client.builder()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(serviceEndpoint, REGION))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("dummyKey", "dummySecret")))
.build();
}
}
}
And a sample test:
public class CsvS3UploadServiceIntegrationTest extends AbstractAmazonS3Test {
private static final String SUCCESS_CSV = "a,b";
private static final String STANDARD_STORAGE = "STANDARD";
#Autowired
private AmazonS3 s3;
#Autowired
private S3ConfigurationProperties properties;
#Autowired
private CsvS3UploadService service;
#Before
public void setUp() {
s3.createBucket(properties.getBucketName());
}
#After
public void tearDown() {
final String bucketName = properties.getBucketName();
s3.listObjects(bucketName).getObjectSummaries().stream()
.map(S3ObjectSummary::getKey)
.forEach(key -> s3.deleteObject(bucketName, key));
s3.deleteBucket(bucketName);
}
#Test
public void uploadSuccessfulCsv() {
service.uploadSuccessfulCsv(SUCCESS_CSV);
final S3ObjectSummary s3ObjectSummary = getOnlyFileFromS3();
assertThat(s3ObjectSummary.getKey(), containsString("-success.csv"));
assertThat(s3ObjectSummary.getETag(), is("b345e1dc09f20fdefdea469f09167892"));
assertThat(s3ObjectSummary.getStorageClass(), is(STANDARD_STORAGE));
assertThat(s3ObjectSummary.getSize(), is(3L));
}
private S3ObjectSummary getOnlyFileFromS3() {
final ObjectListing listing = s3.listObjects(properties.getBucketName());
final List<S3ObjectSummary> objects = listing.getObjectSummaries();
assertThat(objects, iterableWithSize(1));
return Iterables.getOnlyElement(objects);
}
}
And the code under test:
#Service
#RequiredArgsConstructor
#EnableConfigurationProperties(S3ConfigurationProperties.class)
public class CsvS3UploadServiceImpl implements CsvS3UploadService {
private static final String CSV_MIME_TYPE = CSV_UTF_8.toString();
private final AmazonS3 amazonS3;
private final S3ConfigurationProperties properties;
private final S3ObjectKeyService s3ObjectKeyService;
#Override
public void uploadSuccessfulCsv(final String source) {
final String key = s3ObjectKeyService.getSuccessKey();
doUpload(source, key, getObjectMetadata(source));
}
private void doUpload(final String source, final String key, final ObjectMetadata metadata) {
try (ReaderInputStream in = new ReaderInputStream(new StringReader(source), UTF_8)) {
final PutObjectRequest request = new PutObjectRequest(properties.getBucketName(), key, in, metadata);
amazonS3.putObject(request);
} catch (final IOException ioe) {
throw new CsvUploadException("Unable to upload " + key, ioe);
}
}
private ObjectMetadata getObjectMetadata(final String source) {
final ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(CSV_MIME_TYPE);
metadata.setContentLength(source.getBytes(UTF_8).length);
metadata.setContentMD5(getMD5ChecksumAsBase64(source));
metadata.setSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());
return metadata;
}
private String getMD5ChecksumAsBase64(final String source) {
final HashCode md5 = Hashing.md5().hashString(source, UTF_8);
return Base64.getEncoder().encodeToString(md5.asBytes());
}
}
It seems the only way to provide custom amazonS3 bean for ResourceLoader is to inject it manually. The test looks like
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration(classes = S3DownUpLoaderTest.S3Configuration.class)
public class S3DownUpLoaderTest implements ApplicationContextAware {
private static final String BUCKET_NAME = "bucket";
#ClassRule
public static LocalStackContainer localstack = new LocalStackContainer().withServices(S3);
#Autowired
S3DownUpLoader s3DownUpLoader;
#Autowired
SimpleStorageProtocolResolver resourceLoader;
#Autowired
AmazonS3 amazonS3;
#Before
public void setUp(){
amazonS3.createBucket(BUCKET_NAME);
}
#Test
public void someTestA() throws IOException {
....
}
#After
public void tearDown(){
ObjectListing object_listing = amazonS3.listObjects(QLM_BUCKET_NAME);
while (true) {
for (S3ObjectSummary summary : object_listing.getObjectSummaries()) {
amazonS3.deleteObject(BUCKET_NAME, summary.getKey());
}
// more object_listing to retrieve?
if (object_listing.isTruncated()) {
object_listing = amazonS3.listNextBatchOfObjects(object_listing);
} else {
break;
}
};
amazonS3.deleteBucket(BUCKET_NAME);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext instanceof ConfigurableApplicationContext) {
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
configurableApplicationContext.addProtocolResolver(this.resourceLoader);
}
}
public static class S3Configuration {
#Bean
public S3DownUpLoader s3DownUpLoader(ResourceLoader resourceLoader){
return new S3DownUpLoader(resourceLoader);
}
#Bean(destroyMethod = "shutdown")
public AmazonS3 amazonS3() {
return AmazonS3ClientBuilder
.standard()
.withEndpointConfiguration(localstack.getEndpointConfiguration(S3))
.withCredentials(localstack.getDefaultCredentialsProvider())
.build();
}
#Bean
public SimpleStorageProtocolResolver resourceLoader(){
return new SimpleStorageProtocolResolver(amazonS3());
}
}

AutoMapper IMappingEngine ConfigurationStore Initialize Not Happening

AutoMapper Version Used : 3.3.10
[TestClass]
public class AppControllerTests
{
private IMappingEngine _mappingEngine = null;
private ConfigurationStore _configurationStore = null;
[TestInitialize]
public void SetUp()
{
_configurationStore = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers);
_configurationStore.AddProfile(new AutoMapperProfile.AppProfile());
_mappingEngine = new MappingEngine(_configurationStore);
}
[TestMethod]
public void GetAppByAccountID()
{
// Error line
var mappingResult = _mappingEngine.Map<Category>(categoryList).AsQueryable();
}
}
public class AppProfile : Profile
{
protected override void Configure()
{
AutoMapperMappingConfigurations();
}
public void AutoMapperMappingConfigurations()
{
Mapper.CreateMap<DomainModels.Category, Category>().ReverseMap();
}
}
Exception:
An exception of type 'AutoMapper.AutoMapperMappingException'
occurred in AutoMapper.dll but was not handled in user code.
Suspect the
_configurationStore.AddProfile(new OOS.PresentationModelService.AutoMapperProfile.AppProfile());
is not able to create an istance of AppProfile if i write the manual mapping it's working as expected.
_configurationStore.CreateMap<Category, Category>().ReverseMap();

how to make custom error feedback messages in SignInPanel in Wicket

I am implementing a LoginPage with Wicket, and I am not getting it, how to write the custom Feedback messages, for ex, "Password is wrong", "Username is wrong" or "Accound is locked out" (the last example should be a bit more difficult because it is related to Ldap/Ldap error messages I think.. But I think there is an easier way for the second two, with the properties file of my LoginPage or something like that.. I tried to change the default Wicket "login failed" message, and this through the properties' file of my page, I just added "signFailed=Sign in failed TEST", and it got changed.. but didn't got it how to tell the user why! Pass or username is wrong!
here the implementation:
public class LoginPage extends SampleManagementPage {
private static final long serialVersionUID = -8585718500226951823L;
private SignInPanel signIn;
public LoginPage() {
signIn = new SignInPanel("signInPanel");
add(signIn);
}
}
and my SampleManagementPage extends WebPage!
here the properties' file of LoginPage:
page.title=Login for Sample Management
signInFailed=Sign in failed TEST
The reason why you are able to change only the signFailed error message, is that wicket SignInPanel throws only this particular error in case it's sign-in form fails to authenticate. To see that, you can open the source code of SignInPanel.java.
One way to overcome the problem and produce your own error messages, is write your own sign-in panel. I m not saying it is the only way but it worked for me :)
public class LoginPanel extends Panel {
private static final long serialVersionUID = -1662154893824849377L;
private static final String SIGN_IN_FORM = "signInForm";
private boolean includeRememberMe = true;
private boolean rememberMe = true;
private String password;
private String username;
public LoginPanel(final String id, final boolean includeRememberMe) {
super(id);
this.includeRememberMe = includeRememberMe;
add(new FeedbackPanel("feedback"));
add(new SignInForm(SIGN_IN_FORM));
}
#Override
protected void onConfigure() {
if (isSignedIn() == false) {
IAuthenticationStrategy authenticationStrategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
String[] data = authenticationStrategy.load();
if ((data != null) && (data.length > 1)) {
if (signIn(data[0], data[1])) {
username = data[0];
password = data[1];
onSignInRemembered();
} else {
authenticationStrategy.remove();
}
}
}
super.onConfigure();
}
private boolean signIn(String username, String password) {
return AuthenticatedWebSession.get().signIn(username, password);
}
private boolean userExists(String username) {
return ((MyWebSession) AuthenticatedWebSession.get()).userExists(username);
}
private boolean isSignedIn() {
return AuthenticatedWebSession.get().isSignedIn();
}
protected void onSignInFailed() {
error(getLocalizer().getString("signInFailed", this, "Wrong password"));
}
private void onUserExistsFailed() {
error(getLocalizer().getString("userExistsFailed", this, "User does not exist"));
}
protected void onSignInSucceeded() {
continueToOriginalDestination();
setResponsePage(getApplication().getHomePage());
}
protected void onSignInRemembered() {
continueToOriginalDestination();
throw new RestartResponseException(getApplication().getHomePage());
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public LoginPanel(final String id) {
this(id, true);
}
public final class SignInForm extends StatelessForm<LoginPanel> {
private static final long serialVersionUID = 1L;
public SignInForm(final String id) {
super(id);
setModel(new CompoundPropertyModel<LoginPanel>(LoginPanel.this));
add(new TextField<String>("username"));
add(new PasswordTextField("password"));
WebMarkupContainer rememberMeRow = new WebMarkupContainer("rememberMeRow");
add(rememberMeRow);
rememberMeRow.add(new CheckBox("rememberMe"));
rememberMeRow.setVisible(includeRememberMe);
}
#Override
public final void onSubmit() {
IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
if (!userExists(username)) {
onUserExistsFailed();
strategy.remove();
return;
}
if (signIn(getUsername(), getPassword())) {
if (rememberMe == true) {
strategy.save(username, password);
} else {
strategy.remove();
}
onSignInSucceeded();
} else {
onSignInFailed();
strategy.remove();
}
}
}
}
public class MyWebSession extends AuthenticatedWebSession {
private static final long serialVersionUID = -401924496527311251L;
public MyWebSession(Request request) {
super(request);
}
public boolean userExists(String username) {
// business login
}
#Override
public boolean authenticate(String username, String password) {
// business login
}
#Override
public Roles getRoles() {
Roles roles = new Roles();
roles.add(Roles.USER);
return roles;
}
}